diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d234804dd8..3222a0467a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,6 +6,7 @@ jobs: build: runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} + if: "!contains(github.event.head_commit.message, '[skip ci]')" strategy: matrix: os: [ ubuntu-latest , windows-latest , macos-latest ] @@ -13,7 +14,7 @@ jobs: experimental: [ false ] steps: - - uses: actions/checkout@v2.3.2 + - uses: actions/checkout@v2 - uses: actions/cache@v2 with: path: ~/.m2/repository @@ -21,9 +22,9 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@v1.4.2 + uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} - name: Build with mvnw run: | - ./mvnw clean install + ./mvnw -V clean install diff --git a/.travis.yml b/.travis.yml index 5ff4e3b8b8..34758b8d66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,13 +34,6 @@ jobs: dist: bionic env: BUILD=coveralls if: "type = push && repo = pmd/pmd && fork = false" - - name: "macosx - mvn verify" - os: osx - env: BUILD=deploy - - name: "windows - mvn verify" - os: windows - env: BUILD=deploy - language: shell - stage: publish name: "Release Build - Publish" os: linux @@ -49,7 +42,7 @@ jobs: env: BUILD=publish before_install: - - bash .travis/before_install.sh "11.0.8+10" + - bash .travis/before_install.sh "11" - source ${HOME}/java.env install: true before_script: true diff --git a/.travis/all-java.xml b/.travis/all-java.xml index 2a4f1345dc..72ed667e22 100644 --- a/.travis/all-java.xml +++ b/.travis/all-java.xml @@ -6,13 +6,321 @@ xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd"> Every java rule in PMD which is used for the regression tests with pmdtester - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.travis/before_install.sh b/.travis/before_install.sh index c0f9c55853..c58c93d09d 100644 --- a/.travis/before_install.sh +++ b/.travis/before_install.sh @@ -13,30 +13,36 @@ bash .travis/configure-maven.sh bash .travis/install-openjdk.sh $OPENJDK_VERSION +function install_jdk() { + LOCAL_DIR=$1 + TARGET_DIR=$2 + DOWNLOAD_URL=$3 + ARCHIVE=$(basename $DOWNLOAD_URL) + + mkdir -p ${LOCAL_DIR} + mkdir -p ${TARGET_DIR} + if [ ! -e ${LOCAL_DIR}/${ARCHIVE} ]; then + log_info "Downloading from ${DOWNLOAD_URL} to ${LOCAL_DIR}" + wget --directory-prefix ${LOCAL_DIR} --timestamping --continue ${DOWNLOAD_URL} + else + log_info "Skipped download, file ${LOCAL_DIR}/${ARCHIVE} already exists" + fi + log_info "Extracting to ${TARGET_DIR}" + tar --extract --file ${LOCAL_DIR}/${ARCHIVE} -C ${TARGET_DIR} --strip-components=1 +} + if travis_isLinux; then + change_ruby_version gem install bundler bundle config set --local path vendor/bundle bundle config set --local with release_notes_preprocessing bundle install - # install openjdk8 for integration test - LOCAL_DIR=${HOME}/.cache/jdk8 - TARGET_DIR=${HOME}/openjdk8 - OPENJDK8_ARCHIVE=OpenJDK8U-jdk_x64_linux_hotspot_8u265b01.tar.gz - DOWNLOAD_URL=https://pmd-code.org/openjdk/jdk-8u265b01/${OPENJDK8_ARCHIVE} - mkdir -p ${LOCAL_DIR} - mkdir -p ${TARGET_DIR} - if [ ! -e ${LOCAL_DIR}/${OPENJDK8_ARCHIVE} ]; then - log_info "Downloading from ${DOWNLOAD_URL} to ${LOCAL_DIR}" - wget --directory-prefix ${LOCAL_DIR} --timestamping --continue ${DOWNLOAD_URL} - else - log_info "Skipped download, file ${LOCAL_DIR}/${OPENJDK8_ARCHIVE} already exists" - fi - log_info "Extracting to ${TARGET_DIR}" - tar --extract --file ${LOCAL_DIR}/${OPENJDK8_ARCHIVE} -C ${TARGET_DIR} --strip-components=1 - log_info "OpenJDK8 can be used via -Djava8.home=${TARGET_DIR}" - + # install openjdk8 for integration test and pmd-regression-tests + install_jdk "${HOME}/.cache/openjdk" "${HOME}/openjdk8" "https://pmd-code.org/openjdk/latest/jdk-8-linux64.tar.gz" + log_info "OpenJDK8 can be used via -Djava8.home=${HOME}/openjdk8" + log_info "OpenJDK8 can be used from ${HOME}/openjdk8" else - log_info "Not setting up ruby for ${TRAVIS_OS_NAME}." + log_info "Not setting up ruby and additional jvms for ${TRAVIS_OS_NAME}." exit 0 fi diff --git a/.travis/common-functions.sh b/.travis/common-functions.sh index 3148dd9796..c217bb3c6f 100755 --- a/.travis/common-functions.sh +++ b/.travis/common-functions.sh @@ -57,3 +57,8 @@ function travis_isWindows() { function get_pom_version() { echo $(./mvnw -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.0.0:exec) } + +function change_ruby_version() { + source "$HOME/.rvm/scripts/rvm" + rvm use ruby-2.7 +} diff --git a/.travis/install-openjdk.sh b/.travis/install-openjdk.sh index 1e07be76e9..af59870c50 100644 --- a/.travis/install-openjdk.sh +++ b/.travis/install-openjdk.sh @@ -2,36 +2,38 @@ set -e # -# AdoptOpenJDK Builds from: -# https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/tag/jdk-11.0.4%2B11 +# Downloads AdoptOpenJDK Builds from +# https://pmd-code.org/openjdk/latest/jdk-11-linux64.tar.gz +# https://pmd-code.org/openjdk/latest/jdk-11-windows64.zip +# https://pmd-code.org/openjdk/latest/jdk-11-mac64.tar.gz +# +# The Build are originally from: +# https://github.com/AdoptOpenJDK/openjdk11-binaries/releases # source .travis/logger.sh source .travis/common-functions.sh -# VERSION_TAG e.g. "11.0.4+11" or "13+33" -VERSION_TAG=$1 -OPENJDK_MAJOR=${VERSION_TAG/.*/} -OPENJDK_MAJOR=${OPENJDK_MAJOR/+*/} -#BASE_URL=https://github.com/AdoptOpenJDK/openjdk${OPENJDK_MAJOR}-binaries/releases/download -BASE_URL=https://pmd-code.org/openjdk +# OPENJDK_VERSION e.g. "11" +OPENJDK_VERSION=$1 +BASE_URL=https://pmd-code.org/openjdk/latest/jdk-${OPENJDK_VERSION}- -log_info "Installing OpenJDK${OPENJDK_MAJOR}U ${VERSION_TAG} for ${TRAVIS_OS_NAME}" +log_info "Installing OpenJDK${OPENJDK_VERSION} for ${TRAVIS_OS_NAME}" if travis_isOSX; then - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_mac_hotspot_${VERSION_TAG/+/_}.tar.gz + DOWNLOAD_URL=${BASE_URL}mac64.tar.gz COMPONENTS_TO_STRIP=3 # e.g. jdk-11.0.3+7/Contents/Home/bin/java elif travis_isWindows; then - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_windows_hotspot_${VERSION_TAG/+/_}.zip + DOWNLOAD_URL=${BASE_URL}windows64.zip else - DOWNLOAD_URL=${BASE_URL}/jdk-${VERSION_TAG/+/%2B}/OpenJDK${OPENJDK_MAJOR}U-jdk_x64_linux_hotspot_${VERSION_TAG/+/_}.tar.gz + DOWNLOAD_URL=${BASE_URL}linux64.tar.gz COMPONENTS_TO_STRIP=1 # e.g. openjdk-11.0.3+7/bin/java fi OPENJDK_ARCHIVE=$(basename $DOWNLOAD_URL) LOCAL_DIR=${HOME}/.cache/openjdk -TARGET_DIR=${HOME}/openjdk${OPENJDK_MAJOR} +TARGET_DIR=${HOME}/openjdk${OPENJDK_VERSION} mkdir -p ${LOCAL_DIR} mkdir -p ${TARGET_DIR} diff --git a/.travis/project-list.xml b/.travis/project-list.xml index 5471d6f2e3..600061f674 100644 --- a/.travis/project-list.xml +++ b/.travis/project-list.xml @@ -1,7 +1,7 @@ +xsi:noNamespaceSchemaLocation="projectlist_1_1_0.xsd"> Standard Projects @@ -9,6 +9,19 @@ xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd"> git https://github.com/checkstyle/checkstyle checkstyle-8.10 + + .*/target/test-classes/com/puppycrawl/tools/checkstyle/.* + .*/target/generated-sources/.* + + + echo -n "$(pwd)/target/classes:$(pwd)/target/test-classes:"; cat classpath.txt @@ -16,6 +29,39 @@ xsi:noNamespaceSchemaLocation="projectlist_1_0_0.xsd"> git https://github.com/spring-projects/spring-framework v5.0.6.RELEASE + + > build.gradle < classpath.txt +]]> + cat classpath.txt - + + @@ -9,8 +10,8 @@
- - + +
diff --git a/docs/_includes/custom/panel_scroll.html b/docs/_includes/custom/panel_scroll.html deleted file mode 100644 index 8dc89de981..0000000000 --- a/docs/_includes/custom/panel_scroll.html +++ /dev/null @@ -1,27 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/_includes/custom/shuffle_panel.html b/docs/_includes/custom/shuffle_panel.html index ffe3b4adb0..8842c67745 100644 --- a/docs/_includes/custom/shuffle_panel.html +++ b/docs/_includes/custom/shuffle_panel.html @@ -1,3 +1,4 @@ +{% comment %} @@ -5,14 +6,14 @@ - - + + - +{% endcomment %} {% assign titlemaker = include.titlemaker | default: "page.title" %} {% assign include_tags = include.tags | split: "," %} @@ -22,21 +23,20 @@ {% assign panel_id = include.title | downcase | strip | replace: ' ', '-' | prepend: "shuffle-panel-" %}
-
- - - {% if include.image != "" and include.image != nil %} -
- - - - +
+ {% if include.fa-icon != "" and include.fa-icon != nil %} +
+

+ + +

{% endif %} +
+ {{ include.title }} +
-
{{ include.title }}
-
- +

{{ include.description }}

diff --git a/docs/_includes/custom/usermap.html b/docs/_includes/custom/usermap.html deleted file mode 100644 index f90b5c2cb6..0000000000 --- a/docs/_includes/custom/usermap.html +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/docs/_includes/custom/usermapcomplex.html b/docs/_includes/custom/usermapcomplex.html deleted file mode 100644 index c75a65254a..0000000000 --- a/docs/_includes/custom/usermapcomplex.html +++ /dev/null @@ -1,91 +0,0 @@ -
- - - - - - - - - - - - - - - - - - - - - -
- -
diff --git a/docs/_includes/custom/xpath_fun_doc.html b/docs/_includes/custom/xpath_fun_doc.html index 12a7781adf..90276cbb18 100644 --- a/docs/_includes/custom/xpath_fun_doc.html +++ b/docs/_includes/custom/xpath_fun_doc.html @@ -28,7 +28,7 @@ {{ fun.shortDescription }} + class="fas fa-ellipsis-h"> diff --git a/docs/_includes/disqus.html b/docs/_includes/disqus.html deleted file mode 100644 index 4fad7a25f3..0000000000 --- a/docs/_includes/disqus.html +++ /dev/null @@ -1,16 +0,0 @@ -{% if site.disqus_shortname %} - -
- - -{% endif %} \ No newline at end of file diff --git a/docs/_includes/feedback.html b/docs/_includes/feedback.html deleted file mode 100644 index 6031797fc8..0000000000 --- a/docs/_includes/feedback.html +++ /dev/null @@ -1,13 +0,0 @@ -
  • -{% if site.feedback_text %} - {% assign feedback_text = site.feedback_text %} -{% else %} - {% assign feedback_text = "Feedback" %} -{% endif %} - -{% if site.feedback_link %} - -{% else %} - -{% endif %} -
  • diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html index 12d9065323..6879e1fcb6 100755 --- a/docs/_includes/footer.html +++ b/docs/_includes/footer.html @@ -1,9 +1,12 @@
    diff --git a/docs/_includes/google_analytics.html b/docs/_includes/google_analytics.html deleted file mode 100644 index 56b2ee88c5..0000000000 --- a/docs/_includes/google_analytics.html +++ /dev/null @@ -1,6 +0,0 @@ - - -{% if site.google_analytics %} - - -{% endif %} \ No newline at end of file diff --git a/docs/_includes/head.html b/docs/_includes/head.html index 8e115b3fa0..806206b577 100644 --- a/docs/_includes/head.html +++ b/docs/_includes/head.html @@ -4,35 +4,18 @@ {{ page.title }} | {{ site.site_title }} - - - - - - - - + + - - - + + + + + + + - - - - - - - - - - - - - + diff --git a/docs/_includes/head_print.html b/docs/_includes/head_print.html deleted file mode 100644 index 8f10c28f86..0000000000 --- a/docs/_includes/head_print.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - -{% if page.homepage == true %} {{site.homepage_title}} {% elsif page.title %}{{ page.title }}{% endif %} | {{ site.site_title }} - - - - - - - - - - - - - - - - - - - diff --git a/docs/_includes/important.html b/docs/_includes/important.html index af8824b9f4..02b194627e 100644 --- a/docs/_includes/important.html +++ b/docs/_includes/important.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/_includes/initialize_shuffle.html b/docs/_includes/initialize_shuffle.html deleted file mode 100644 index 73354870b7..0000000000 --- a/docs/_includes/initialize_shuffle.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - diff --git a/docs/_includes/note.html b/docs/_includes/note.html index 2c1cfe967c..e8ed7ab24a 100644 --- a/docs/_includes/note.html +++ b/docs/_includes/note.html @@ -1 +1 @@ - + diff --git a/docs/_includes/sidebar.html b/docs/_includes/sidebar.html index 0a3474f9ba..8348086ad3 100644 --- a/docs/_includes/sidebar.html +++ b/docs/_includes/sidebar.html @@ -59,12 +59,4 @@ {% endif %} {% endfor %} {% endfor %} - - - - diff --git a/docs/_includes/taglogic.html b/docs/_includes/taglogic.html index c2f76b014b..5b8cdd18eb 100644 --- a/docs/_includes/taglogic.html +++ b/docs/_includes/taglogic.html @@ -1,4 +1,4 @@ -

    The following pages and posts are tagged with

    +

    The following pages and posts are tagged with

    {% assign thisTag = page.tagName %} diff --git a/docs/_includes/tip.html b/docs/_includes/tip.html index faf48afd86..dd2b08449e 100644 --- a/docs/_includes/tip.html +++ b/docs/_includes/tip.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/docs/_includes/toc.html b/docs/_includes/toc.html index e573d982fe..48701ec3fc 100644 --- a/docs/_includes/toc.html +++ b/docs/_includes/toc.html @@ -1,12 +1,5 @@ - - - +{% comment %} +Note: The content of the div-element is filled by javascript. See customscripts.js. +{% endcomment %}
    diff --git a/docs/_includes/topnav.html b/docs/_includes/topnav.html index 39a172ad5a..daf50ba7c4 100644 --- a/docs/_includes/topnav.html +++ b/docs/_includes/topnav.html @@ -1,77 +1,53 @@ -",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t("",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,h,l,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[a],l=!1,e[u]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(e[u]-h)&&(n=Math.abs(e[u]-h),o=this.items[s],this.direction=l?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.leftthis.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter; +this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.spinner",{version:"1.12.1",defaultElement:"",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e=this._super(),i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);null!=n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var e=this.element[0]===t.ui.safeActiveElement(this.document[0]);e||(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===t.ui.safeActiveElement(this.document[0])?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap("").parent().append("")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&this.uiSpinner.height()>0&&this.uiSpinner.height(this.uiSpinner.height())},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){var i,s,n;return"culture"===t||"numberFormat"===t?(i=this._parse(this.element.val()),this.options[t]=e,this.element.val(this._format(i)),void 0):(("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(s=this.buttons.first().find(".ui-icon"),this._removeClass(s,null,this.options.icons.up),this._addClass(s,null,e.up),n=this.buttons.last().find(".ui-icon"),this._removeClass(n,null,this.options.icons.down),this._addClass(n,null,e.down)),this._super(t,e),void 0)},_setOptionDisabled:function(t){this._super(t),this._toggleClass(this.uiSpinner,null,"ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable")},_setOptions:r(function(t){this._super(t)}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var t=this.value();return null===t?!1:t===this._adjustValue(t)},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.prop("disabled",!1).removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:r(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:r(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:r(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:r(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(r(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),t.uiBackCompat!==!1&&t.widget("ui.spinner",t.ui.spinner,{_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml())},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""}}),t.ui.spinner,t.widget("ui.tabs",{version:"1.12.1",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var t=/#.*$/;return function(e){var i,s;i=e.href.replace(t,""),s=location.href.replace(t,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return e.hash.length>1&&i===s}}(),_create:function(){var e=this,i=this.options;this.running=!1,this._addClass("ui-tabs","ui-widget ui-widget-content"),this._toggleClass("ui-tabs-collapsible",null,i.collapsible),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var e=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===e&&(s&&this.tabs.each(function(i,n){return t(n).attr("aria-controls")===s?(e=i,!1):void 0}),null===e&&(e=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===e||-1===e)&&(e=this.tabs.length?0:!1)),e!==!1&&(e=this.tabs.index(this.tabs.eq(e)),-1===e&&(e=i?!1:0)),!i&&e===!1&&this.anchors.length&&(e=0),e},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(e){var i=t(t.ui.safeActiveElement(this.document[0])).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(e)){switch(e.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:s++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:n=!1,s--;break;case t.ui.keyCode.END:s=this.anchors.length-1;break;case t.ui.keyCode.HOME:s=0;break;case t.ui.keyCode.SPACE:return e.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case t.ui.keyCode.ENTER:return e.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}e.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),e.ctrlKey||e.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.trigger("focus"))},_handlePageNav:function(e){return e.altKey&&e.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):e.altKey&&e.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).trigger("focus"),t},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):(this._super(t,e),"collapsible"===t&&(this._toggleClass("ui-tabs-collapsible",null,e),e||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(e),"heightStyle"===t&&this._setupHeightStyle(e),void 0)},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this,i=this.tabs,s=this.anchors,n=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).attr({role:"presentation",tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=t(),this.anchors.each(function(i,s){var n,o,a,r=t(s).uniqueId().attr("id"),h=t(s).closest("li"),l=h.attr("aria-controls");e._isLocal(s)?(n=s.hash,a=n.substring(1),o=e.element.find(e._sanitizeSelector(n))):(a=h.attr("aria-controls")||t({}).uniqueId()[0].id,n="#"+a,o=e.element.find(n),o.length||(o=e._createPanel(a),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":a,"aria-labelledby":r}),o.attr("aria-labelledby",r)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(e){return t("
    ").attr("id",e).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(e){var i,s,n;for(t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1),n=0;s=this.tabs[n];n++)i=t(s),e===!0||-1!==t.inArray(n,e)?(i.attr("aria-disabled","true"),this._addClass(i,null,"ui-state-disabled")):(i.removeAttr("aria-disabled"),this._removeClass(i,null,"ui-state-disabled"));this.options.disabled=e,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,e===!0)},_setupEvents:function(e){var i={};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),o=n.closest("li"),a=o[0]===s[0],r=a&&i.collapsible,h=r?t():this._getPanelForTab(o),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():o,newPanel:h};e.preventDefault(),o.hasClass("ui-state-disabled")||o.hasClass("ui-tabs-loading")||this.running||a&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(o),this.active=a?t():o,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(o),e),this._toggle(e,c))},_toggle:function(e,i){function s(){o.running=!1,o._trigger("activate",e,i)}function n(){o._addClass(i.newTab.closest("li"),"ui-tabs-active","ui-state-active"),a.length&&o.options.show?o._show(a,o.options.show,s):(a.show(),s())}var o=this,a=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){o._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n()}):(this._removeClass(i.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),a.length&&r.length?i.oldTab.attr("tabIndex",-1):a.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),a.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+t.ui.escapeSelector(e)+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(e){var i=this.options.disabled;i!==!1&&(void 0===e?i=!1:(e=this._getIndex(e),i=t.isArray(i)?t.map(i,function(t){return t!==e?t:null}):t.map(this.tabs,function(t,i){return i!==e?i:null})),this._setOptionDisabled(i))},disable:function(e){var i=this.options.disabled;if(i!==!0){if(void 0===e)i=!0;else{if(e=this._getIndex(e),-1!==t.inArray(e,i))return;i=t.isArray(i)?t.merge([e],i).sort():[e]}this._setOptionDisabled(i)}},load:function(e,i){e=this._getIndex(e);var s=this,n=this.tabs.eq(e),o=n.find(".ui-tabs-anchor"),a=this._getPanelForTab(n),r={tab:n,panel:a},h=function(t,e){"abort"===e&&s.panels.stop(!1,!0),s._removeClass(n,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===s.xhr&&delete s.xhr};this._isLocal(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(n,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,n){setTimeout(function(){a.html(t),s._trigger("load",i,r),h(n,e)},1)}).fail(function(t,e){setTimeout(function(){h(t,e)},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href").replace(/#.*$/,""),beforeSend:function(e,o){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:o},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),t.uiBackCompat!==!1&&t.widget("ui.tabs",t.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}}),t.ui.tabs,t.widget("ui.tooltip",{version:"1.12.1",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var e=t(this).attr("title")||"";return t("").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))},_removeDescribedBy:function(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=t("
    ").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=t([])},_setOption:function(e,i){var s=this;this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s.element[0],e.close(n,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var e=t(this);return e.is("[title]")?e.data("ui-tooltip-title",e.attr("title")).removeAttr("title"):void 0}))},_enable:function(){this.disabledTitles.each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))}),this.disabledTitles=t([])},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(e,s),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s||s.nodeType||s.jquery?this._open(e,t,s):(i=s.call(t[0],function(i){n._delay(function(){t.data("ui-tooltip-open")&&(e&&(e.type=o),this._open(e,t,i))})}),i&&this._open(e,t,i),void 0)},_open:function(e,i,s){function n(t){l.of=t,a.is(":hidden")||a.position(l)}var o,a,r,h,l=t.extend({},this.options.position);if(s){if(o=this._find(i))return o.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(e&&"mouseover"===e.type?i.attr("title",""):i.removeAttr("title")),o=this._tooltip(i),a=o.tooltip,this._addDescribedBy(i,a.attr("id")),a.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),h=t("
    ").html(a.find(".ui-tooltip-content").html()),h.removeAttr("name").find("[name]").removeAttr("name"),h.removeAttr("id").find("[id]").removeAttr("id"),h.appendTo(this.liveRegion),this.options.track&&e&&/^mouse/.test(e.type)?(this._on(this.document,{mousemove:n}),n(e)):a.position(t.extend({of:i},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){a.is(":visible")&&(n(l.of),clearInterval(r))},t.fx.interval)),this._trigger("open",e,{tooltip:a})}},_registerCloseHandlers:function(e,i){var s={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var s=t.Event(e);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),e&&"mouseover"!==e.type||(s.mouseleave="close"),e&&"focusin"!==e.type||(s.focusout="close"),this._on(!0,i,s)},close:function(e){var i,s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);return o?(i=o.tooltip,o.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),o.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),o.closing=!0,this._trigger("close",e,{tooltip:i}),o.hiding||(o.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(e){var i=t("
    ").attr("role","tooltip"),s=t("
    ").appendTo(i),n=i.uniqueId().attr("id");return this._addClass(s,"ui-tooltip-content"),this._addClass(i,"ui-tooltip","ui-widget ui-widget-content"),i.appendTo(this._appendTo(e)),this.tooltips[n]={element:e,tooltip:i}},_find:function(t){var e=t.data("ui-tooltip-id");return e?this.tooltips[e]:null},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){var e=t.closest(".ui-front, dialog");return e.length||(e=this.document[0].body),e},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur"),o=s.element;n.target=n.currentTarget=o[0],e.close(n,!0),t("#"+i).remove(),o.data("ui-tooltip-title")&&(o.attr("title")||o.attr("title",o.data("ui-tooltip-title")),o.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),t.uiBackCompat!==!1&&t.widget("ui.tooltip",t.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}}),t.ui.tooltip}); \ No newline at end of file diff --git a/docs/assets/navgoco-0.2.1/src/jquery.navgoco.css b/docs/assets/navgoco-0.2.1/src/jquery.navgoco.css new file mode 100644 index 0000000000..a094ab8eee --- /dev/null +++ b/docs/assets/navgoco-0.2.1/src/jquery.navgoco.css @@ -0,0 +1,69 @@ +.nav, .nav ul, .nav li { + list-style: none; +} + +.nav ul { + padding: 0; + margin: 0 0 0 18px; +} + +.nav { + padding: 4px; + margin: 0px; +} + +.nav > li { + margin: 4px 0; +} + +.nav > li li { + margin: 2px 0; +} + +.nav a { + color: #333; + display: block; + outline: none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + text-decoration: none; +} + +.nav li > a > span { + float: right; + font-size: 19px; + font-weight: bolder; +} + +.nav li > a:hover > span { + color: #fff; +} + +.nav li > a > span:after { + content: '\25be'; +} +.nav li.open > a > span:after { + content: '\25b4'; +} + +.nav a:hover, .nav li.active > a { + background-color: #5D5D5D; + color: #f5f5f5; +} + +.nav > li.active > a { + background-color: #4D90FE; +} + +.nav li a { + font-size: 12px; + line-height: 18px; + padding: 2px 10px; +} + +.nav > li > a { + font-size: 14px; + line-height: 20px; + padding: 4px 10px; +} \ No newline at end of file diff --git a/docs/js/jquery.navgoco.min.js b/docs/assets/navgoco-0.2.1/src/jquery.navgoco.min.js old mode 100755 new mode 100644 similarity index 100% rename from docs/js/jquery.navgoco.min.js rename to docs/assets/navgoco-0.2.1/src/jquery.navgoco.min.js diff --git a/docs/css/bootstrap.min.css b/docs/css/bootstrap.min.css deleted file mode 100755 index 7b4112f07e..0000000000 --- a/docs/css/bootstrap.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.2 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{/*color:#000!important;*/text-shadow:none!important;/*background:0 0!important*/;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px \9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important;visibility:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;margin-top:-10px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/docs/css/customstyles.css b/docs/css/customstyles.css index d505dbd8de..22d69a1b6a 100644 --- a/docs/css/customstyles.css +++ b/docs/css/customstyles.css @@ -208,17 +208,16 @@ p.post-meta {font-size: 80%; color: #777;} .entry-date{font-size:14px;font-size:0.875rem;line-height:1.71429;margin-bottom:0;text-transform:uppercase;} /* search area */ -#search-demo-container ul#results-container { +ul#results-container { list-style: none; font-size: 12px; background-color: white; position: absolute; - top: 40px; /* if you change anything about the nav, you'll prob. need to reset the top and left values here.*/ - left: 20px; + top: 50px; /* if you change anything about the nav, you'll prob. need to reset the top and left values here.*/ z-index: -1; - width:223px; border-left: 1px solid #dedede; box-shadow: 2px 3px 2px #dedede; + padding: 0px; } @@ -230,21 +229,11 @@ ul#results-container a:hover { color: black; } +ul#results-container li a { + border-top:1px solid whitesmoke; + margin:10px; +} -#search-demo-container a:hover { - color: black; -} -#search-input { - padding: .5em; - margin-left:20px; - width:20em; - font-size: 0.8em; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - float: right; - margin-top:10px; -} /* end search */ .filter-options { @@ -394,6 +383,7 @@ background-color: #347DBE; } ul#mysidebar { + display: block; border-radius:0px; } @@ -493,9 +483,6 @@ figcaption { } -table.dataTable thead { - background-color: #444; -} table td { hyphens: auto; } @@ -802,9 +789,6 @@ dd {margin-left:20px;} margin:0px; margin-bottom:6px; } -.panel-heading { - font-weight: bold; -} .note code, .alert code, .warning code, div#toc code, h2 code, h3 code, h4 code { color: inherit; @@ -959,10 +943,6 @@ a.no_icon:after padding-left: 0; } -.btn-default { - margin-bottom: 10px; -} - /* algolia search */ .search { @@ -1073,27 +1053,6 @@ table thead th code.highlighter-rouge { background-color: #f0f0f0; } -#userMap { - overflow-x: auto; - overflow-y: auto; - padding: 20px; - min-width: 770px; -} - -#userMap .active { - background-color: #d6f5d6; - border:1px solid #555; - font-weight: bold; -} - -h2.userMapTitle { - font-family: Arial; -} - -#userMap a:hover { - text-decoration: none; - } - div.arrow { max-width: 50px; margin-left: 15px; @@ -1105,57 +1064,19 @@ div.content { max-width: 110px } -#userMap div.arrow, #userMap div.content { - float: left; -} - .clearfix { clear: both; } -#userMap div.arrow { - position: relative; - top: 30px; -} - .box1 { margin-left:0px; } -button.btn.btn-default.btn-lg.modalButton1 { - margin-left: -20px; -} - div.box.box1 { margin-left: -20px; } -#userMap .btn-lg { - width: 100px; - height: 80px; - -} - -#userMap .complexArrow { - font-size: 22px; - margin: 0px 10px; -} - - -#userMap .btn-lg .active { - background-color: #d6f5d6; -} - -#userMap .btn-lg { - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - font-size: 14px; - } - /* * Let's target IE to respect aspect ratios and sizes for img tags containing SVG files * diff --git a/docs/css/font-awesome.min.css b/docs/css/font-awesome.min.css deleted file mode 100644 index 08e68ec0c0..0000000000 --- a/docs/css/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('fonts/fontawesome-webfont.eot?v=4.2.0');src:url('fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"} \ No newline at end of file diff --git a/docs/css/fonts/FontAwesome.otf b/docs/css/fonts/FontAwesome.otf deleted file mode 100644 index f7936cc1e7..0000000000 Binary files a/docs/css/fonts/FontAwesome.otf and /dev/null differ diff --git a/docs/css/fonts/fontawesome-webfont.eot b/docs/css/fonts/fontawesome-webfont.eot deleted file mode 100644 index 33b2bb8005..0000000000 Binary files a/docs/css/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/docs/css/fonts/fontawesome-webfont.svg b/docs/css/fonts/fontawesome-webfont.svg deleted file mode 100644 index 1ee89d4368..0000000000 --- a/docs/css/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,565 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/css/fonts/fontawesome-webfont.ttf b/docs/css/fonts/fontawesome-webfont.ttf deleted file mode 100644 index ed9372f8ea..0000000000 Binary files a/docs/css/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/docs/css/fonts/fontawesome-webfont.woff b/docs/css/fonts/fontawesome-webfont.woff deleted file mode 100644 index 8b280b98fa..0000000000 Binary files a/docs/css/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/docs/css/fonts/fontawesome-webfont.woff2 b/docs/css/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 3311d58514..0000000000 Binary files a/docs/css/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/docs/css/lavish-bootstrap.css b/docs/css/lavish-bootstrap.css deleted file mode 100644 index c2af93e598..0000000000 --- a/docs/css/lavish-bootstrap.css +++ /dev/null @@ -1,5898 +0,0 @@ -/* CSS generated by http://lavishbootstrap.com */ -/*! normalize.css v2.1.0 | MIT License | git.io/normalize */ -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} -audio, -canvas, -video { - display: inline-block; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden] { - display: none; -} -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -a:focus { - outline: thin dotted; -} -a:active, -a:hover { - outline: 0; -} -h1 { - font-size: 2em; - margin: 0.67em 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} -mark { - background: #ff0; - color: #000; -} -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} -pre { - white-space: pre-wrap; -} -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} -small { - font-size: 80%; -} -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 0; -} -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} -legend { - border: 0; - padding: 0; -} -button, -input, -select, -textarea { - font-family: inherit; - font-size: 100%; - margin: 0; -} -button, -input { - line-height: normal; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; - padding: 0; -} -input[type="search"] { - -webkit-appearance: textfield; - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; - box-sizing: content-box; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} -textarea { - overflow: auto; - vertical-align: top; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -@media print { - * { - text-shadow: none !important; - color: #000 !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 2cm .5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -*, -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.428571429; - /*color: #77777a; */ - background-color: #ffffff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -button, -input, -select[multiple], -textarea { - background-image: none; -} -a { - color: #248EC2; - text-decoration: none; -} -a:hover, -a:focus { - text-decoration: underline; -} -a:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -img { - vertical-align: middle; -} -.img-responsive { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - padding: 4px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - display: inline-block; - max-width: 100%; - height: auto; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #bac9c2; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - margin: -1px; - padding: 0; - overflow: hidden; - clip: rect(0 0 0 0); - border: 0; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16.099999999999998px; - font-weight: 200; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small { - font-size: 85%; -} -cite { - font-style: normal; -} -.text-muted { - color: #f9faf9; -} -.text-primary { - color: #74ab50; -} -.text-warning { - color: #c09853; -} -.text-danger { - color: #b94a48; -} -.text-success { - color: #468847; -} -.text-info { - color: #3a87ad; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 500; - line-height: 1.1; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small { - font-weight: normal; - line-height: 1; - color: #f9faf9; -} -h1, -h2, -h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h4, -h5, -h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -h1 small, -.h1 small { - font-size: 24px; -} -h2 small, -.h2 small { - font-size: 18px; -} -h3 small, -.h3 small, -h4 small, -.h4 small { - font-size: 14px; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #bac9c2; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-left: 5px; - padding-right: 5px; -} -dl { - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.428571429; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - clear: left; - text-align: right; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - - } - .dl-horizontal dd:after { - clear: both; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - - } - .dl-horizontal dd:after { - clear: both; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #f9faf9; -} -abbr.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - border-left: 5px solid #bac9c2; -} -blockquote p { - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} -blockquote p:last-child { - margin-bottom: 0; -} -blockquote small { - display: block; - line-height: 1.428571429; - color: #f9faf9; -} -blockquote small:before { - content: '\2014 \00A0'; -} -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #bac9c2; - border-left: 0; -} -blockquote.pull-right p, -blockquote.pull-right small { - text-align: right; -} -blockquote.pull-right small:before { - content: ''; -} -blockquote.pull-right small:after { - content: '\00A0 \2014'; -} -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} -address { - display: block; - margin-bottom: 20px; - font-style: normal; - line-height: 1.428571429; -} -code, -pre { - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #444; - background-color: #f0f0f0; - white-space: nowrap; - border-radius: 4px; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.428571429; - word-break: break-all; - word-wrap: break-word; - color: #77777a; - background-color: #f5f5f5; - border: 1px solid #cccccc; - border-radius: 4px; -} -pre.prettyprint { - margin-bottom: 20px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - margin-right: auto; - margin-left: auto; - padding-left: 15px; - padding-right: 15px; -} -.container:before, -.container:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.container:after { - clear: both; -} -.container:before, -.container:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.container:after { - clear: both; -} -.row { - margin-left: -15px; - margin-right: -15px; -} -.row:before, -.row:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.row:after { - clear: both; -} -.row:before, -.row:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.row:after { - clear: both; -} -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11, -.col-xs-12, -.col-sm-1, -.col-sm-2, -.col-sm-3, -.col-sm-4, -.col-sm-5, -.col-sm-6, -.col-sm-7, -.col-sm-8, -.col-sm-9, -.col-sm-10, -.col-sm-11, -.col-sm-12, -.col-md-1, -.col-md-2, -.col-md-3, -.col-md-4, -.col-md-5, -.col-md-6, -.col-md-7, -.col-md-8, -.col-md-9, -.col-md-10, -.col-md-11, -.col-md-12, -.col-lg-1, -.col-lg-2, -.col-lg-3, -.col-lg-4, -.col-lg-5, -.col-lg-6, -.col-lg-7, -.col-lg-8, -.col-lg-9, -.col-lg-10, -.col-lg-11, -.col-lg-12 { - position: relative; - min-height: 1px; - padding-left: 15px; - padding-right: 15px; -} -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11 { - float: left; -} -.col-xs-1 { - width: 8.333333333333332%; -} -.col-xs-2 { - width: 16.666666666666664%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-4 { - width: 33.33333333333333%; -} -.col-xs-5 { - width: 41.66666666666667%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-7 { - width: 58.333333333333336%; -} -.col-xs-8 { - width: 66.66666666666666%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-10 { - width: 83.33333333333334%; -} -.col-xs-11 { - width: 91.66666666666666%; -} -.col-xs-12 { - width: 100%; -} -@media (min-width: 768px) { - .container { - max-width: 750px; - } - .col-sm-1, - .col-sm-2, - .col-sm-3, - .col-sm-4, - .col-sm-5, - .col-sm-6, - .col-sm-7, - .col-sm-8, - .col-sm-9, - .col-sm-10, - .col-sm-11 { - float: left; - } - .col-sm-1 { - width: 8.333333333333332%; - } - .col-sm-2 { - width: 16.666666666666664%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-4 { - width: 33.33333333333333%; - } - .col-sm-5 { - width: 41.66666666666667%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-7 { - width: 58.333333333333336%; - } - .col-sm-8 { - width: 66.66666666666666%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-10 { - width: 83.33333333333334%; - } - .col-sm-11 { - width: 91.66666666666666%; - } - .col-sm-12 { - width: 100%; - } - .col-sm-push-1 { - left: 8.333333333333332%; - } - .col-sm-push-2 { - left: 16.666666666666664%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-4 { - left: 33.33333333333333%; - } - .col-sm-push-5 { - left: 41.66666666666667%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-7 { - left: 58.333333333333336%; - } - .col-sm-push-8 { - left: 66.66666666666666%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-10 { - left: 83.33333333333334%; - } - .col-sm-push-11 { - left: 91.66666666666666%; - } - .col-sm-pull-1 { - right: 8.333333333333332%; - } - .col-sm-pull-2 { - right: 16.666666666666664%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-4 { - right: 33.33333333333333%; - } - .col-sm-pull-5 { - right: 41.66666666666667%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-7 { - right: 58.333333333333336%; - } - .col-sm-pull-8 { - right: 66.66666666666666%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-10 { - right: 83.33333333333334%; - } - .col-sm-pull-11 { - right: 91.66666666666666%; - } - .col-sm-offset-1 { - margin-left: 8.333333333333332%; - } - .col-sm-offset-2 { - margin-left: 16.666666666666664%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-4 { - margin-left: 33.33333333333333%; - } - .col-sm-offset-5 { - margin-left: 41.66666666666667%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-7 { - margin-left: 58.333333333333336%; - } - .col-sm-offset-8 { - margin-left: 66.66666666666666%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-10 { - margin-left: 83.33333333333334%; - } - .col-sm-offset-11 { - margin-left: 91.66666666666666%; - } -} -@media (min-width: 992px) { - .container { - max-width: 970px; - } - .col-md-1, - .col-md-2, - .col-md-3, - .col-md-4, - .col-md-5, - .col-md-6, - .col-md-7, - .col-md-8, - .col-md-9, - .col-md-10, - .col-md-11 { - float: left; - } - .col-md-1 { - width: 8.333333333333332%; - } - .col-md-2 { - width: 16.666666666666664%; - } - .col-md-3 { - width: 25%; - } - .col-md-4 { - width: 33.33333333333333%; - } - .col-md-5 { - width: 41.66666666666667%; - } - .col-md-6 { - width: 50%; - } - .col-md-7 { - width: 58.333333333333336%; - } - .col-md-8 { - width: 66.66666666666666%; - } - .col-md-9 { - width: 75%; - } - .col-md-10 { - width: 83.33333333333334%; - } - .col-md-11 { - width: 91.66666666666666%; - } - .col-md-12 { - width: 100%; - } - .col-md-push-0 { - left: auto; - } - .col-md-push-1 { - left: 8.333333333333332%; - } - .col-md-push-2 { - left: 16.666666666666664%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-4 { - left: 33.33333333333333%; - } - .col-md-push-5 { - left: 41.66666666666667%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-7 { - left: 58.333333333333336%; - } - .col-md-push-8 { - left: 66.66666666666666%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-10 { - left: 83.33333333333334%; - } - .col-md-push-11 { - left: 91.66666666666666%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-pull-1 { - right: 8.333333333333332%; - } - .col-md-pull-2 { - right: 16.666666666666664%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-4 { - right: 33.33333333333333%; - } - .col-md-pull-5 { - right: 41.66666666666667%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-7 { - right: 58.333333333333336%; - } - .col-md-pull-8 { - right: 66.66666666666666%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-10 { - right: 83.33333333333334%; - } - .col-md-pull-11 { - right: 91.66666666666666%; - } - .col-md-offset-0 { - margin-left: 0; - } - .col-md-offset-1 { - margin-left: 8.333333333333332%; - } - .col-md-offset-2 { - margin-left: 16.666666666666664%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-4 { - margin-left: 33.33333333333333%; - } - .col-md-offset-5 { - margin-left: 41.66666666666667%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-7 { - margin-left: 58.333333333333336%; - } - .col-md-offset-8 { - margin-left: 66.66666666666666%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-10 { - margin-left: 83.33333333333334%; - } - .col-md-offset-11 { - margin-left: 91.66666666666666%; - } -} -@media (min-width: 1200px) { - .container { - max-width: 1170px; - } - .col-lg-1, - .col-lg-2, - .col-lg-3, - .col-lg-4, - .col-lg-5, - .col-lg-6, - .col-lg-7, - .col-lg-8, - .col-lg-9, - .col-lg-10, - .col-lg-11 { - float: left; - } - .col-lg-1 { - width: 8.333333333333332%; - } - .col-lg-2 { - width: 16.666666666666664%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-4 { - width: 33.33333333333333%; - } - .col-lg-5 { - width: 41.66666666666667%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-7 { - width: 58.333333333333336%; - } - .col-lg-8 { - width: 66.66666666666666%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-10 { - width: 83.33333333333334%; - } - .col-lg-11 { - width: 91.66666666666666%; - } - .col-lg-12 { - width: 100%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-push-1 { - left: 8.333333333333332%; - } - .col-lg-push-2 { - left: 16.666666666666664%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-4 { - left: 33.33333333333333%; - } - .col-lg-push-5 { - left: 41.66666666666667%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-7 { - left: 58.333333333333336%; - } - .col-lg-push-8 { - left: 66.66666666666666%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-10 { - left: 83.33333333333334%; - } - .col-lg-push-11 { - left: 91.66666666666666%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-pull-1 { - right: 8.333333333333332%; - } - .col-lg-pull-2 { - right: 16.666666666666664%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-4 { - right: 33.33333333333333%; - } - .col-lg-pull-5 { - right: 41.66666666666667%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-7 { - right: 58.333333333333336%; - } - .col-lg-pull-8 { - right: 66.66666666666666%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-10 { - right: 83.33333333333334%; - } - .col-lg-pull-11 { - right: 91.66666666666666%; - } - .col-lg-offset-0 { - margin-left: 0; - } - .col-lg-offset-1 { - margin-left: 8.333333333333332%; - } - .col-lg-offset-2 { - margin-left: 16.666666666666664%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-4 { - margin-left: 33.33333333333333%; - } - .col-lg-offset-5 { - margin-left: 41.66666666666667%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-7 { - margin-left: 58.333333333333336%; - } - .col-lg-offset-8 { - margin-left: 66.66666666666666%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-10 { - margin-left: 83.33333333333334%; - } - .col-lg-offset-11 { - margin-left: 91.66666666666666%; - } -} -table { - max-width: 100%; - background-color: transparent; -} -th { - text-align: left; -} -.table { - width: 100%; - margin-bottom: 20px; -} -.table thead > tr > th, -.table tbody > tr > th, -.table tfoot > tr > th, -.table thead > tr > td, -.table tbody > tr > td, -.table tfoot > tr > td { - padding: 8px; - line-height: 1.428571429; - vertical-align: top; - border-top: 1px solid #77777a; -} -.table thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #77777a; -} -.table caption + thead tr:first-child th, -.table colgroup + thead tr:first-child th, -.table thead:first-child tr:first-child th, -.table caption + thead tr:first-child td, -.table colgroup + thead tr:first-child td, -.table thead:first-child tr:first-child td { - border-top: 0; -} -.table tbody + tbody { - border-top: 2px solid #77777a; -} -.table .table { - background-color: #ffffff; -} -.table-condensed thead > tr > th, -.table-condensed tbody > tr > th, -.table-condensed tfoot > tr > th, -.table-condensed thead > tr > td, -.table-condensed tbody > tr > td, -.table-condensed tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #77777a; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #77777a; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-child(odd) > td, -.table-striped > tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover > td, -.table-hover > tbody > tr:hover > th { - background-color: #f5f5f5; -} -table col[class*="col-"] { - float: none; - display: table-column; -} -table td[class*="col-"], -table th[class*="col-"] { - float: none; - display: table-cell; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; - border-color: #d6e9c6; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td { - background-color: #d0e9c6; - border-color: #c9e2b3; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; - border-color: #eed3d7; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td { - background-color: #ebcccc; - border-color: #e6c1c7; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; - border-color: #fbeed5; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td { - background-color: #faf2cc; - border-color: #f8e5be; -} -@media (max-width: 768px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - overflow-x: scroll; - border: 1px solid #77777a; - } - .table-responsive > .table { - margin-bottom: 0; - background-color: #fff; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > thead > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > thead > tr:last-child > td, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #77777a; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - /* IE8-9 */ - - line-height: normal; -} -input[type="file"] { - display: block; -} -select[multiple], -select[size] { - height: auto; -} -select optgroup { - font-size: inherit; - font-style: inherit; - font-family: inherit; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -input[type="number"]::-webkit-outer-spin-button, -input[type="number"]::-webkit-inner-spin-button { - height: auto; -} -.form-control:-moz-placeholder { - color: #f9faf9; -} -.form-control::-moz-placeholder { - color: #f9faf9; -} -.form-control:-ms-input-placeholder { - color: #f9faf9; -} -.form-control::-webkit-input-placeholder { - color: #f9faf9; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.428571429; - color: #4aadd6; - vertical-align: middle; - background-color: #ffffff; - border: 1px solid #cccccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #bac9c2; -} -textarea.form-control { - height: auto; -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - display: block; - min-height: 20px; - margin-top: 10px; - margin-bottom: 10px; - padding-left: 20px; - vertical-align: middle; -} -.radio label, -.checkbox label { - display: inline; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - vertical-align: middle; - font-weight: normal; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -.radio[disabled], -.radio-inline[disabled], -.checkbox[disabled], -.checkbox-inline[disabled], -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"], -fieldset[disabled] .radio, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm { - height: auto; -} -.input-lg { - height: 45px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -select.input-lg { - height: 45px; - line-height: 45px; -} -textarea.input-lg { - height: auto; -} -.has-warning .help-block, -.has-warning .control-label { - color: #c09853; -} -.has-warning .form-control { - border-color: #c09853; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-warning .form-control:focus { - border-color: #a47e3c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -} -.has-warning .input-group-addon { - color: #c09853; - border-color: #c09853; - background-color: #fcf8e3; -} -.has-error .help-block, -.has-error .control-label { - color: #b94a48; -} -.has-error .form-control { - border-color: #b94a48; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-error .form-control:focus { - border-color: #953b39; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -} -.has-error .input-group-addon { - color: #b94a48; - border-color: #b94a48; - background-color: #f2dede; -} -.has-success .help-block, -.has-success .control-label { - color: #468847; -} -.has-success .form-control { - border-color: #468847; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} -.has-success .form-control:focus { - border-color: #356635; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -} -.has-success .input-group-addon { - color: #468847; - border-color: #468847; - background-color: #dff0d8; -} -.form-control-static { - margin-bottom: 0; - padding-top: 7px; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #b7b7b9; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} -.form-horizontal .control-label, -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - margin-top: 0; - margin-bottom: 0; - padding-top: 7px; -} -.form-horizontal .form-group { - margin-left: -15px; - margin-right: -15px; -} -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.form-horizontal .form-group:after { - clear: both; -} -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.form-horizontal .form-group:after { - clear: both; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - text-align: right; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.428571429; - text-align: center; - vertical-align: middle; - cursor: pointer; - border: 1px solid transparent; - border-radius: 4px; - white-space: nowrap; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} -.btn:focus { - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; -} -.btn:active, -.btn.active { - outline: 0; - background-image: none; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - pointer-events: none; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-default { - color: #333333; - background-color: #ffffff; - border-color: #cccccc; -} -.btn-default:hover, -.btn-default:focus, -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - color: #333333; - background-color: #ebebeb; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - background-image: none; -} -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #ffffff; - border-color: #cccccc; -} -.btn-primary { - color: #ffffff; - background-color: #74ab50; - border-color: #689a48; -} -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - color: #ffffff; - background-color: #618f43; - border-color: #4c7034; -} -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - background-image: none; -} -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #74ab50; - border-color: #689a48; -} -.btn-warning { - color: #ffffff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - color: #ffffff; - background-color: #ed9c28; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - background-image: none; -} -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-danger { - color: #ffffff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - color: #ffffff; - background-color: #d2322d; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - background-image: none; -} -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-success { - color: #ffffff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - color: #ffffff; - background-color: #47a447; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - background-image: none; -} -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-info { - color: #ffffff; - background-color: #347DBE; - border-color: #347DBE; -} -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - color: #ffffff; - background-color: #015CAE; - border-color: #015CAE; -} -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - background-image: none; -} -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-link { - color: #74ab50; - font-weight: normal; - cursor: pointer; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #517738; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #f9faf9; - text-decoration: none; -} -.btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -.btn-sm, -.btn-xs { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs { - padding: 1px 5px; -} -.btn-block { - display: block; - width: 100%; - padding-left: 0; - padding-right: 0; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - transition: height 0.35s ease; -} -@font-face { - font-family: 'Glyphicons Halflings'; - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - -webkit-font-smoothing: antialiased; -} -.glyphicon-asterisk:before { - content: "\2a"; -} -.glyphicon-plus:before { - content: "\2b"; -} -.glyphicon-euro:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -.glyphicon-briefcase:before { - content: "\1f4bc"; -} -.glyphicon-calendar:before { - content: "\1f4c5"; -} -.glyphicon-pushpin:before { - content: "\1f4cc"; -} -.glyphicon-paperclip:before { - content: "\1f4ce"; -} -.glyphicon-camera:before { - content: "\1f4f7"; -} -.glyphicon-lock:before { - content: "\1f512"; -} -.glyphicon-bell:before { - content: "\1f514"; -} -.glyphicon-bookmark:before { - content: "\1f516"; -} -.glyphicon-fire:before { - content: "\1f525"; -} -.glyphicon-wrench:before { - content: "\1f527"; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid #000000; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - border-bottom: 0 dotted; - content: ""; -} -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - font-size: 14px; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-clip: padding-box; -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.428571429; - color: #77777a; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - text-decoration: none; - color: #ffffff; - background-color: #679DCE; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - outline: 0; - background-color: #679DCE; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #f9faf9; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - cursor: not-allowed; -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.428571429; - color: #f9faf9; -} -.dropdown-backdrop { - position: fixed; - left: 0; - right: 0; - bottom: 0; - top: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0 dotted; - border-bottom: 4px solid #000000; - content: ""; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } -} -.btn-default .caret { - border-top-color: #333333; -} -.btn-primary .caret, -.btn-success .caret, -.btn-warning .caret, -.btn-danger .caret, -.btn-info .caret { - border-top-color: #fff; -} -.dropup .btn-default .caret { - border-bottom-color: #333333; -} -.dropup .btn-primary .caret, -.dropup .btn-success .caret, -.dropup .btn-warning .caret, -.dropup .btn-danger .caret, -.dropup .btn-info .caret { - border-bottom-color: #fff; -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus { - outline: none; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar:before, -.btn-toolbar:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.btn-toolbar:after { - clear: both; -} -.btn-toolbar:before, -.btn-toolbar:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.btn-toolbar:after { - clear: both; -} -.btn-toolbar .btn-group { - float: left; -} -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group, -.btn-toolbar > .btn-group + .btn-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child > .btn:last-child, -.btn-group > .btn-group:first-child > .dropdown-toggle { - border-bottom-right-radius: 0; - border-top-right-radius: 0; -} -.btn-group > .btn-group:last-child > .btn:first-child { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group-xs > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; - padding: 1px 5px; -} -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -.btn-group > .btn + .dropdown-toggle { - padding-left: 8px; - padding-right: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-left: 12px; - padding-right: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.btn-group-vertical > .btn-group:after { - clear: both; -} -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.btn-group-vertical > .btn-group:after { - clear: both; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-bottom-left-radius: 4px; - border-top-right-radius: 0; - border-top-left-radius: 0; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child > .btn:last-child, -.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child > .btn:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified .btn { - float: none; - display: table-cell; - width: 1%; -} -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group.col { - float: none; - padding-left: 0; - padding-right: 0; -} -.input-group .form-control { - width: 100%; - margin-bottom: 0; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 45px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 45px; - line-height: 45px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - text-align: center; - background-color: #bac9c2; - border: 1px solid #cccccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -4px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:active { - z-index: 2; -} -.nav { - margin-bottom: 0; - padding-left: 0; - list-style: none; -} -.nav:before, -.nav:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.nav:after { - clear: both; -} -.nav:before, -.nav:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.nav:after { - clear: both; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #bac9c2; -} -.nav > li.disabled > a { - color: #f9faf9; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #f9faf9; - text-decoration: none; - background-color: transparent; - cursor: not-allowed; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #bac9c2; - border-color: #74ab50; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #dddddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.428571429; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #bac9c2 #bac9c2 #dddddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #4aadd6; - background-color: #ffffff; - border: 1px solid #dddddd; - border-bottom-color: transparent; - cursor: default; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - text-align: center; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } -} -.nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #dddddd; - margin-right: 0; -} -.nav-tabs.nav-justified > .active > a { - border-bottom-color: #ffffff; -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 5px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #ffffff; - background-color: #74ab50; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - text-align: center; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - border-bottom: 1px solid #dddddd; - margin-right: 0; -} -.nav-tabs-justified > .active > a { - border-bottom-color: #ffffff; -} -.tabbable:before, -.tabbable:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.tabbable:after { - clear: both; -} -.tabbable:before, -.tabbable:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.tabbable:after { - clear: both; -} -.tab-content > .tab-pane, -.pill-content > .pill-pane { - display: none; -} -.tab-content > .active, -.pill-content > .active { - display: block; -} -.nav .caret { - border-top-color: #74ab50; - border-bottom-color: #74ab50; -} -.nav a:hover .caret { - border-top-color: #517738; - border-bottom-color: #517738; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-right-radius: 0; - border-top-left-radius: 0; -} -.navbar { - position: relative; - z-index: 1000; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -.navbar:before, -.navbar:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar:after { - clear: both; -} -.navbar:before, -.navbar:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar:after { - clear: both; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -.navbar-header:before, -.navbar-header:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar-header:after { - clear: both; -} -.navbar-header:before, -.navbar-header:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar-header:after { - clear: both; -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - max-height: 340px; - overflow-x: visible; - padding-right: 15px; - padding-left: 15px; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - -webkit-overflow-scrolling: touch; -} -.navbar-collapse:before, -.navbar-collapse:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar-collapse:after { - clear: both; -} -.navbar-collapse:before, -.navbar-collapse:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.navbar-collapse:after { - clear: both; -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-collapse .navbar-nav.navbar-left:first-child { - margin-left: -15px; - } - .navbar-collapse .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } - .navbar-collapse .navbar-text:last-child { - margin-right: 0; - } -} -.container > .navbar-header, -.container > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - z-index: 1030; - top: 0; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; -} -.navbar-brand { - float: left; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - margin-right: 15px; - padding: 9px 10px; - margin-top: 8px; - margin-bottom: 8px; - background-color: transparent; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } -} -.navbar-form { - margin-left: -15px; - margin-right: -15px; - padding: 10px 15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - margin-top: 8px; - margin-bottom: 8px; -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - border: 0; - margin-left: 0; - margin-right: 0; - padding-top: 0; - padding-bottom: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-right-radius: 0; - border-top-left-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-nav.pull-right > li > .dropdown-menu, -.navbar-nav > li > .dropdown-menu.pull-right { - left: auto; - right: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-text { - float: left; - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - margin-left: 15px; - margin-right: 15px; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777777; -} -.navbar-default .navbar-nav > li > a { - color: #777777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #cccccc; - background-color: transparent; -} -.navbar-default .navbar-toggle { - border-color: #dddddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #dddddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #cccccc; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e6e6e6; -} -.navbar-default .navbar-nav > .dropdown > a:hover .caret, -.navbar-default .navbar-nav > .dropdown > a:focus .caret { - border-top-color: #333333; - border-bottom-color: #333333; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - background-color: #e7e7e7; - color: #555555; -} -.navbar-default .navbar-nav > .open > a .caret, -.navbar-default .navbar-nav > .open > a:hover .caret, -.navbar-default .navbar-nav > .open > a:focus .caret { - border-top-color: #555555; - border-bottom-color: #555555; -} -.navbar-default .navbar-nav > .dropdown > a .caret { - border-top-color: #777777; - border-bottom-color: #777777; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #cccccc; - background-color: transparent; - } -} -.navbar-default .navbar-link { - color: #777777; -} -.navbar-default .navbar-link:hover { - color: #333333; -} -.navbar-inverse { - background-color: #74ab50; - border-color: #5c8840; -} -.navbar-inverse .navbar-brand { - color: #f9faf9; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #ffffff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #f9faf9; -} -.navbar-inverse .navbar-nav > li > a { - color: #f9faf9; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #ffffff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #ffffff; - background-color: #5c8840; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444444; - background-color: transparent; -} -.navbar-inverse .navbar-toggle { - border-color: #333333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #ffffff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #649345; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - background-color: #5c8840; - color: #ffffff; -} -.navbar-inverse .navbar-nav > .dropdown > a:hover .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -.navbar-inverse .navbar-nav > .dropdown > a .caret { - border-top-color: #f9faf9; - border-bottom-color: #f9faf9; -} -.navbar-inverse .navbar-nav > .open > a .caret, -.navbar-inverse .navbar-nav > .open > a:hover .caret, -.navbar-inverse .navbar-nav > .open > a:focus .caret { - border-top-color: #ffffff; - border-bottom-color: #ffffff; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #5c8840; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #f9faf9; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #ffffff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #ffffff; - background-color: #5c8840; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444444; - background-color: transparent; - } -} -.navbar-inverse .navbar-link { - color: #f9faf9; -} -.navbar-inverse .navbar-link:hover { - color: #ffffff; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - content: "/\00a0"; - padding: 0 5px; - color: #cccccc; -} -.breadcrumb > .active { - color: #f9faf9; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - line-height: 1.428571429; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; - margin-left: -1px; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-bottom-left-radius: 4px; - border-top-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-bottom-right-radius: 4px; - border-top-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - background-color: #bac9c2; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 2; - color: #ffffff; - background-color: #74ab50; - border-color: #74ab50; - cursor: default; -} -.pagination > .disabled > span, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #f9faf9; - background-color: #ffffff; - border-color: #dddddd; - cursor: not-allowed; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-bottom-left-radius: 6px; - border-top-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-bottom-right-radius: 6px; - border-top-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-bottom-right-radius: 3px; - border-top-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - list-style: none; - text-align: center; -} -.pager:before, -.pager:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.pager:after { - clear: both; -} -.pager:before, -.pager:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.pager:after { - clear: both; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #bac9c2; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #f9faf9; - background-color: #ffffff; - cursor: not-allowed; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #ffffff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -.label[href]:hover, -.label[href]:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} - -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #dde3dd; -} -.label-primary { - background-color: #74ab50; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #5c8840; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - color: #ffffff; - line-height: 1; - vertical-align: baseline; - white-space: nowrap; - text-align: center; - background-color: #f9faf9; - border-radius: 10px; -} -.badge:empty { - display: none; -} -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} -.btn .badge { - position: relative; - top: -1px; -} -a.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #74ab50; - background-color: #ffffff; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding: 30px; - margin-bottom: 30px; - font-size: 21px; - font-weight: 200; - line-height: 2.1428571435; - color: inherit; - background-color: #bac9c2; -} -.jumbotron h1 { - line-height: 1; - color: inherit; -} -.jumbotron p { - line-height: 1.4; -} -.container .jumbotron { - border-radius: 6px; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-left: 60px; - padding-right: 60px; - } - .jumbotron h1 { - font-size: 63px; - } -} -.thumbnail { - padding: 4px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - display: inline-block; - max-width: 100%; - height: auto; - display: block; -} -.thumbnail > img { - display: block; - max-width: 100%; - height: auto; -} -a.thumbnail:hover, -a.thumbnail:focus { - border-color: #74ab50; -} -.thumbnail > img { - margin-left: auto; - margin-right: auto; -} -.thumbnail .caption { - padding: 9px; - color: #77777a; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable { - padding-right: 35px; -} -.alert-dismissable .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - background-color: #dff0d8; - border-color: #d6e9c6; - color: #468847; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #356635; -} -.alert-info { - background-color: #d9edf7; - border-color: #bce8f1; - color: #3a87ad; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #2d6987; -} -.alert-warning { - background-color: #fcf8e3; - border-color: #fbeed5; - color: #c09853; -} -.alert-warning hr { - border-top-color: #f8e5be; -} -.alert-warning .alert-link { - color: #a47e3c; -} -.alert-danger { - background-color: #f2dede; - border-color: #eed3d7; - color: #b94a48; -} -.alert-danger hr { - border-top-color: #e6c1c7; -} -.alert-danger .alert-link { - color: #953b39; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-moz-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 0 0; - } - to { - background-position: 40px 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - overflow: hidden; - height: 20px; - margin-bottom: 20px; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} -.progress-bar { - float: left; - width: 0%; - height: 100%; - font-size: 12px; - color: #ffffff; - text-align: center; - background-color: #74ab50; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-transition: width 0.6s ease; - transition: width 0.6s ease; -} -.progress-striped .progress-bar { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} -.progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -moz-animation: progress-bar-stripes 2s linear infinite; - -ms-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media, -.media .media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media-object { - display: block; -} -.media-heading { - margin: 0 0 5px; -} -.media > .pull-left { - margin-right: 10px; -} -.media > .pull-right { - margin-left: 10px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - margin-bottom: 20px; - padding-left: 0; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #ffffff; - border: 1px solid #dddddd; -} -.list-group-item:first-child { - border-top-right-radius: 4px; - border-top-left-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -a.list-group-item { - color: #555555; -} -a.list-group-item .list-group-item-heading { - color: #333333; -} -a.list-group-item:hover, -a.list-group-item:focus { - text-decoration: none; - background-color: #f5f5f5; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #ffffff; - background-color: #74ab50; - border-color: #74ab50; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #e1edda; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #ffffff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); -} -.panel-body { - padding: 15px; -} -.panel-body:before, -.panel-body:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.panel-body:after { - clear: both; -} -.panel-body:before, -.panel-body:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.panel-body:after { - clear: both; -} -.panel > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item { - border-width: 1px 0; -} -.panel > .list-group .list-group-item:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} -.panel > .list-group .list-group-item:last-child { - border-bottom: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.panel > .table { - margin-bottom: 0; -} -.panel > .panel-body + .table { - border-top: 1px solid #77777a; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-right-radius: 3px; - border-top-left-radius: 3px; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; -} -.panel-title > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #dddddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; - overflow: hidden; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse .panel-body { - border-top: 1px solid #dddddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #dddddd; -} -.panel-default { - border-color: #dddddd; -} -.panel-default > .panel-heading { - color: #77777a; - background-color: #f5f5f5; - border-color: #dddddd; -} -.panel-default > .panel-heading + .panel-collapse .panel-body { - border-top-color: #dddddd; -} -.panel-default > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #dddddd; -} -.panel-primary { - border-color: #74ab50; -} -.panel-primary > .panel-heading { - color: #ffffff; - background-color: #74ab50; - border-color: #74ab50; -} -.panel-primary > .panel-heading + .panel-collapse .panel-body { - border-top-color: #74ab50; -} -.panel-primary > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #74ab50; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #468847; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-warning { - border-color: #fbeed5; -} -.panel-warning > .panel-heading { - color: #c09853; - background-color: #fcf8e3; - border-color: #fbeed5; -} -.panel-warning > .panel-heading + .panel-collapse .panel-body { - border-top-color: #fbeed5; -} -.panel-warning > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #fbeed5; -} -.panel-danger { - border-color: #eed3d7; -} -.panel-danger > .panel-heading { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} -.panel-danger > .panel-heading + .panel-collapse .panel-body { - border-top-color: #eed3d7; -} -.panel-danger > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #eed3d7; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #3a87ad; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #bce8f1; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.5; - filter: alpha(opacity=50); -} -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} -.modal-open { - overflow: hidden; -} -body.modal-open, -.modal-open .navbar-fixed-top, -.modal-open .navbar-fixed-bottom { - margin-right: 15px; -} -.modal { - display: none; - overflow: auto; - overflow-y: scroll; - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; -} -.modal.fade .modal-dialog { - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - transform: translate(0, -25%); - -webkit-transition: -webkit-transform 0.3s ease-out; - -moz-transition: -moz-transform 0.3s ease-out; - -o-transition: -o-transform 0.3s ease-out; - transition: transform 0.3s ease-out; -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-dialog { - margin-left: auto; - margin-right: auto; - width: auto; - padding: 10px; - z-index: 1050; -} -.modal-content { - position: relative; - background-color: #ffffff; - border: 1px solid #999999; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - background-clip: padding-box; - outline: none; -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; - background-color: #000000; -} -.modal-backdrop.fade { - opacity: 0; - filter: alpha(opacity=0); -} -.modal-backdrop.in { - opacity: 0.5; - filter: alpha(opacity=50); -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; - min-height: 16.428571429px; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.428571429; -} -.modal-body { - position: relative; - padding: 20px; -} -.modal-footer { - margin-top: 15px; - padding: 19px 20px 20px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer:before, -.modal-footer:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.modal-footer:after { - clear: both; -} -.modal-footer:before, -.modal-footer:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.modal-footer:after { - clear: both; -} -.modal-footer .btn + .btn { - margin-left: 5px; - margin-bottom: 0; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -@media screen and (min-width: 768px) { - .modal-dialog { - left: 50%; - right: auto; - width: 600px; - padding-top: 30px; - padding-bottom: 30px; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - } -} -.tooltip { - position: absolute; - z-index: 1030; - display: block; - visibility: visible; - font-size: 12px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); -} -.tooltip.in { - opacity: 0.9; - filter: alpha(opacity=90); -} -.tooltip.top { - margin-top: -3px; - padding: 5px 0; -} -.tooltip.right { - margin-left: 3px; - padding: 0 5px; -} -.tooltip.bottom { - margin-top: 3px; - padding: 5px 0; -} -.tooltip.left { - margin-left: -3px; - padding: 0 5px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000000; -} -.tooltip.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-width: 5px 5px 0; - border-top-color: #000000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - right: 5px; - border-width: 5px 5px 0; - border-top-color: #000000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - background-color: #ffffff; - background-clip: padding-box; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - white-space: normal; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - margin: 0; - padding: 8px 14px; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover .arrow { - border-width: 11px; -} -.popover .arrow:after { - border-width: 10px; - content: ""; -} -.popover.top .arrow { - left: 50%; - margin-left: -11px; - border-bottom-width: 0; - border-top-color: #999999; - border-top-color: rgba(0, 0, 0, 0.25); - bottom: -11px; -} -.popover.top .arrow:after { - content: " "; - bottom: 1px; - margin-left: -10px; - border-bottom-width: 0; - border-top-color: #ffffff; -} -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-left-width: 0; - border-right-color: #999999; - border-right-color: rgba(0, 0, 0, 0.25); -} -.popover.right .arrow:after { - content: " "; - left: 1px; - bottom: -10px; - border-left-width: 0; - border-right-color: #ffffff; -} -.popover.bottom .arrow { - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999999; - border-bottom-color: rgba(0, 0, 0, 0.25); - top: -11px; -} -.popover.bottom .arrow:after { - content: " "; - top: 1px; - margin-left: -10px; - border-top-width: 0; - border-bottom-color: #ffffff; -} -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999999; - border-left-color: rgba(0, 0, 0, 0.25); -} -.popover.left .arrow:after { - content: " "; - right: 1px; - border-right-width: 0; - border-left-color: #ffffff; - bottom: -10px; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - overflow: hidden; - width: 100%; -} -.carousel-inner > .item { - display: none; - position: relative; - -webkit-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; - line-height: 1; -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - left: 0; - bottom: 0; - width: 15%; - opacity: 0.5; - filter: alpha(opacity=50); - font-size: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); -} -.carousel-control.left { - background-image: -webkit-gradient(linear, 0% top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0%), color-stop(rgba(0, 0, 0, 0.0001) 100%)); - background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); -} -.carousel-control.right { - left: auto; - right: 0; - background-image: -webkit-gradient(linear, 0% top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0%), color-stop(rgba(0, 0, 0, 0.5) 100%)); - background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); -} -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - opacity: 0.9; - filter: alpha(opacity=90); -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - left: 50%; - z-index: 5; - display: inline-block; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; -} -.carousel-control .icon-prev:before { - content: '\2039'; -} -.carousel-control .icon-next:before { - content: '\203a'; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - margin-left: -30%; - padding-left: 0; - list-style: none; - text-align: center; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - border: 1px solid #ffffff; - border-radius: 10px; - cursor: pointer; -} -.carousel-indicators .active { - margin: 0; - width: 12px; - height: 12px; - background-color: #ffffff; -} -.carousel-caption { - position: absolute; - left: 15%; - right: 15%; - bottom: 20px; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - .carousel-caption { - left: 20%; - right: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after { - content: " "; - /* 1 */ - - display: table; - /* 2 */ - -} -.clearfix:after { - clear: both; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -@media screen and (max-width: 400px) { - @-ms-viewport { - width: 320px; - } -} -.hidden { - display: none !important; - visibility: hidden !important; -} -.visible-xs { - display: none !important; -} -tr.visible-xs { - display: none !important; -} -th.visible-xs, -td.visible-xs { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-xs.visible-sm { - display: block !important; - } - tr.visible-xs.visible-sm { - display: table-row !important; - } - th.visible-xs.visible-sm, - td.visible-xs.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-xs.visible-md { - display: block !important; - } - tr.visible-xs.visible-md { - display: table-row !important; - } - th.visible-xs.visible-md, - td.visible-xs.visible-md { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-xs.visible-lg { - display: block !important; - } - tr.visible-xs.visible-lg { - display: table-row !important; - } - th.visible-xs.visible-lg, - td.visible-xs.visible-lg { - display: table-cell !important; - } -} -.visible-sm { - display: none !important; -} -tr.visible-sm { - display: none !important; -} -th.visible-sm, -td.visible-sm { - display: none !important; -} -@media (max-width: 767px) { - .visible-sm.visible-xs { - display: block !important; - } - tr.visible-sm.visible-xs { - display: table-row !important; - } - th.visible-sm.visible-xs, - td.visible-sm.visible-xs { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-sm.visible-md { - display: block !important; - } - tr.visible-sm.visible-md { - display: table-row !important; - } - th.visible-sm.visible-md, - td.visible-sm.visible-md { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-sm.visible-lg { - display: block !important; - } - tr.visible-sm.visible-lg { - display: table-row !important; - } - th.visible-sm.visible-lg, - td.visible-sm.visible-lg { - display: table-cell !important; - } -} -.visible-md { - display: none !important; -} -tr.visible-md { - display: none !important; -} -th.visible-md, -td.visible-md { - display: none !important; -} -@media (max-width: 767px) { - .visible-md.visible-xs { - display: block !important; - } - tr.visible-md.visible-xs { - display: table-row !important; - } - th.visible-md.visible-xs, - td.visible-md.visible-xs { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-md.visible-sm { - display: block !important; - } - tr.visible-md.visible-sm { - display: table-row !important; - } - th.visible-md.visible-sm, - td.visible-md.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-md.visible-lg { - display: block !important; - } - tr.visible-md.visible-lg { - display: table-row !important; - } - th.visible-md.visible-lg, - td.visible-md.visible-lg { - display: table-cell !important; - } -} -.visible-lg { - display: none !important; -} -tr.visible-lg { - display: none !important; -} -th.visible-lg, -td.visible-lg { - display: none !important; -} -@media (max-width: 767px) { - .visible-lg.visible-xs { - display: block !important; - } - tr.visible-lg.visible-xs { - display: table-row !important; - } - th.visible-lg.visible-xs, - td.visible-lg.visible-xs { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-lg.visible-sm { - display: block !important; - } - tr.visible-lg.visible-sm { - display: table-row !important; - } - th.visible-lg.visible-sm, - td.visible-lg.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-lg.visible-md { - display: block !important; - } - tr.visible-lg.visible-md { - display: table-row !important; - } - th.visible-lg.visible-md, - td.visible-lg.visible-md { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -.hidden-xs { - display: block !important; -} -tr.hidden-xs { - display: table-row !important; -} -th.hidden-xs, -td.hidden-xs { - display: table-cell !important; -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } - tr.hidden-xs { - display: none !important; - } - th.hidden-xs, - td.hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-xs.hidden-sm { - display: none !important; - } - tr.hidden-xs.hidden-sm { - display: none !important; - } - th.hidden-xs.hidden-sm, - td.hidden-xs.hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-xs.hidden-md { - display: none !important; - } - tr.hidden-xs.hidden-md { - display: none !important; - } - th.hidden-xs.hidden-md, - td.hidden-xs.hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-xs.hidden-lg { - display: none !important; - } - tr.hidden-xs.hidden-lg { - display: none !important; - } - th.hidden-xs.hidden-lg, - td.hidden-xs.hidden-lg { - display: none !important; - } -} -.hidden-sm { - display: block !important; -} -tr.hidden-sm { - display: table-row !important; -} -th.hidden-sm, -td.hidden-sm { - display: table-cell !important; -} -@media (max-width: 767px) { - .hidden-sm.hidden-xs { - display: none !important; - } - tr.hidden-sm.hidden-xs { - display: none !important; - } - th.hidden-sm.hidden-xs, - td.hidden-sm.hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } - tr.hidden-sm { - display: none !important; - } - th.hidden-sm, - td.hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-sm.hidden-md { - display: none !important; - } - tr.hidden-sm.hidden-md { - display: none !important; - } - th.hidden-sm.hidden-md, - td.hidden-sm.hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-sm.hidden-lg { - display: none !important; - } - tr.hidden-sm.hidden-lg { - display: none !important; - } - th.hidden-sm.hidden-lg, - td.hidden-sm.hidden-lg { - display: none !important; - } -} -.hidden-md { - display: block !important; -} -tr.hidden-md { - display: table-row !important; -} -th.hidden-md, -td.hidden-md { - display: table-cell !important; -} -@media (max-width: 767px) { - .hidden-md.hidden-xs { - display: none !important; - } - tr.hidden-md.hidden-xs { - display: none !important; - } - th.hidden-md.hidden-xs, - td.hidden-md.hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-md.hidden-sm { - display: none !important; - } - tr.hidden-md.hidden-sm { - display: none !important; - } - th.hidden-md.hidden-sm, - td.hidden-md.hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } - tr.hidden-md { - display: none !important; - } - th.hidden-md, - td.hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-md.hidden-lg { - display: none !important; - } - tr.hidden-md.hidden-lg { - display: none !important; - } - th.hidden-md.hidden-lg, - td.hidden-md.hidden-lg { - display: none !important; - } -} -.hidden-lg { - display: block !important; -} -tr.hidden-lg { - display: table-row !important; -} -th.hidden-lg, -td.hidden-lg { - display: table-cell !important; -} -@media (max-width: 767px) { - .hidden-lg.hidden-xs { - display: none !important; - } - tr.hidden-lg.hidden-xs { - display: none !important; - } - th.hidden-lg.hidden-xs, - td.hidden-lg.hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-lg.hidden-sm { - display: none !important; - } - tr.hidden-lg.hidden-sm { - display: none !important; - } - th.hidden-lg.hidden-sm, - td.hidden-lg.hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-lg.hidden-md { - display: none !important; - } - tr.hidden-lg.hidden-md { - display: none !important; - } - th.hidden-lg.hidden-md, - td.hidden-lg.hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } - tr.hidden-lg { - display: none !important; - } - th.hidden-lg, - td.hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -tr.visible-print { - display: none !important; -} -th.visible-print, -td.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } - .hidden-print { - display: none !important; - } - tr.hidden-print { - display: none !important; - } - th.hidden-print, - td.hidden-print { - display: none !important; - } -} diff --git a/docs/css/pmd-customstyles.css b/docs/css/pmd-customstyles.css index 7683ae54d8..31c8985aad 100644 --- a/docs/css/pmd-customstyles.css +++ b/docs/css/pmd-customstyles.css @@ -1,7 +1,4 @@ -.panel-body { - padding-top: 0cm; -} .landing-page.cat-title { margin-bottom: .5cm; @@ -12,6 +9,16 @@ margin-top: .4cm; } +#grid > div { + margin: 10px 0px; +} +#grid .card-body { + padding-top: 0cm; +} +#grid .card-header { + font-weight: bold; +} + /* Offsets contents by the height of the nav bar */ #topbar-content-offset { overflow: scroll; @@ -84,3 +91,30 @@ details[open] summary { .xpath-fun-doc .code-examples dt { font-weight: normal; } + +.float-right { + float: right; +} + +.float-left { + float: left; +} + +.footer p img { + margin-left: 1em; +} + + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + word-break: break-all; + word-wrap: break-word; + color: #77777a; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} diff --git a/docs/css/printstyles.css b/docs/css/printstyles.css deleted file mode 100644 index 5e55e57651..0000000000 --- a/docs/css/printstyles.css +++ /dev/null @@ -1,160 +0,0 @@ - -/*body.print .container {max-width: 650px;}*/ - -body { - font-size:14px; -} -.nav ul li a {border-top:0px; background-color:transparent; color: #808080; } -#navig a[href] {color: #595959 !important;} -table .table {max-width:650px;} - -#navig li.sectionHead {font-weight: bold; font-size: 18px; color: #595959 !important; } -#navig li {font-weight: normal; } - -#navig a[href]::after { content: leader(".") target-counter(attr(href), page); } - -a[href]::after { - content: " (page " target-counter(attr(href), page) ")" -} - -a[href^="http:"]::after, a[href^="https:"]::after { - content: " (" attr(href) ")"; -} - -a[href] { - color: blue !important; -} -a[href*="mailto"]::after, a[data-toggle="tooltip"]::after, a[href].noCrossRef::after { - content: ""; -} - - -@page { - margin: 60pt 90pt 60pt 90pt; - font-family: sans-serif; - font-style:none; - color: gray; - -} - -.printTitle { - line-height:30pt; - font-size:27pt; - font-weight: bold; - letter-spacing: -.5px; - margin-bottom:25px; -} - -.printSubtitle { - font-size: 19pt; - color: #cccccc !important; - front-family: "Grotesque MT Light"; - line-height: 22pt; - letter-spacing: -.5px; - margin-bottom:20px; -} -.printTitleArea hr { - color: #999999 !important; - height: 2px; - width: 100%; -} - -.printTitleImage { - max-width:300px; - margin-bottom:200px; -} - - -.printTitleImage { - max-width: 250px; -} - -#navig { - /*page-break-before: always;*/ -} - -.copyrightBoilerplate { - page-break-before:always; - font-size:14px; -} - -.lastGeneratedDate { - font-style: italic; - font-size:14px; - color: gray; -} - -.alert a { - text-decoration: none !important; -} - - -body.title { page: title } - -@page title { - @top-left { - content: " "; - } - @top-right { - content: " " - } - @bottom-right { - content: " "; - } - @bottom-left { - content: " "; - } -} - -body.frontmatter { page: frontmatter } -body.frontmatter {counter-reset: page 1} - - -@page frontmatter { - @top-left { - content: prince-script(guideName); - } - @top-right { - content: prince-script(datestamp); - } - @bottom-right { - content: counter(page, lower-roman); - } - @bottom-left { - content: "youremail@domain.com"; } -} - -body.first_page {counter-reset: page 1} - -h1 { string-set: doctitle content() } - -@page { - @top-left { - content: string(doctitle); - font-size: 11px; - font-style: italic; - } - @top-right { - content: prince-script(datestamp); - font-size: 11px; - } - - @bottom-right { - content: "Page " counter(page); - font-size: 11px; - } - @bottom-left { - content: prince-script(guideName); - font-size: 11px; - } -} -.alert { - background-color: #fafafa !important; - border-color: #dedede !important; - color: black; -} - -pre { - background-color: #fafafa; -} - diff --git a/docs/css/theme-green.css b/docs/css/theme-green.css index f6b0d8b1e7..fbc757b84e 100644 --- a/docs/css/theme-green.css +++ b/docs/css/theme-green.css @@ -1,11 +1,11 @@ .summary { color: #808080; - border-left: 5px solid #E50E51; + border-left: 5px solid #4d94ff; font-size:16px; } -h3 {color: #E50E51; } +h3 {color: #4d94ff; } h4 {color: #808080; } .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { @@ -14,20 +14,20 @@ h4 {color: #808080; } } .nav > li.active > a { - background-color: #72ac4a; + background-color: #01c172; } .nav > li > a:hover { - background-color: #72ac4a; + background-color: #01c172; } div.navbar-collapse .dropdown-menu > li > a:hover { - background-color: #72ac4a; + background-color: #01c172; } .nav li.thirdlevel > a { background-color: #FAFAFA !important; - color: #72ac4a; + color: #01c172; font-weight: bold; } @@ -37,24 +37,15 @@ a[data-toggle="tooltip"] { cursor: default; } -.navbar-inverse { - background-color: #72ac4a; +.navbar { + background-color: #01c172; border-color: #5b893c; } -.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { - color: #5b893c; +.navbar .nav-item > .nav-link { + color: white !important; /* bootstrap adds 0.5 transparency which we must override */ } -.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { - background-color: #5b893c; - color: #ffffff; -} - -/* not sure if using this ...*/ -.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { - border-color: #72ac4a !important; -} .btn-primary { color: #ffffff; @@ -67,7 +58,7 @@ a[data-toggle="tooltip"] { .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { - background-color: #72ac4a; + background-color: #01c172; border-color: #5b893c; } @@ -77,7 +68,7 @@ a[data-toggle="tooltip"] { body.print h1 {color: #5b893c !important; font-size:28px;} body.print h2 {color: #595959 !important; font-size:24px;} -body.print h3 {color: #E50E51 !important; font-size:14px;} +body.print h3 {color: #4d94ff !important; font-size:14px;} body.print h4 {color: #679DCE !important; font-size:14px; font-style: italic;} .anchorjs-link:hover { @@ -85,15 +76,15 @@ body.print h4 {color: #679DCE !important; font-size:14px; font-style: italic;} } div.sidebarTitle { - color: #E50E51; + color: #4d94ff; } li.sidebarTitle { margin-top:40px; font-weight:normal; font-size:130%; - color: #ED1951; + color: #4d94ff; margin-bottom:10px; margin-left: 5px; -} \ No newline at end of file +} diff --git a/docs/fonts/FontAwesome.otf b/docs/fonts/FontAwesome.otf deleted file mode 100644 index 81c9ad949b..0000000000 Binary files a/docs/fonts/FontAwesome.otf and /dev/null differ diff --git a/docs/fonts/fontawesome-webfont.eot b/docs/fonts/fontawesome-webfont.eot deleted file mode 100644 index 84677bc0c5..0000000000 Binary files a/docs/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/docs/fonts/fontawesome-webfont.svg b/docs/fonts/fontawesome-webfont.svg deleted file mode 100644 index d907b25ae6..0000000000 --- a/docs/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,520 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/fonts/fontawesome-webfont.ttf b/docs/fonts/fontawesome-webfont.ttf deleted file mode 100644 index 96a3639cdd..0000000000 Binary files a/docs/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/docs/fonts/fontawesome-webfont.woff b/docs/fonts/fontawesome-webfont.woff deleted file mode 100644 index 628b6a52a8..0000000000 Binary files a/docs/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/docs/fonts/glyphicons-halflings-regular.eot b/docs/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index b93a4953ff..0000000000 Binary files a/docs/fonts/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/docs/fonts/glyphicons-halflings-regular.svg b/docs/fonts/glyphicons-halflings-regular.svg deleted file mode 100644 index 94fb5490a2..0000000000 --- a/docs/fonts/glyphicons-halflings-regular.svg +++ /dev/null @@ -1,288 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/fonts/glyphicons-halflings-regular.ttf b/docs/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index 1413fc609a..0000000000 Binary files a/docs/fonts/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/docs/fonts/glyphicons-halflings-regular.woff b/docs/fonts/glyphicons-halflings-regular.woff deleted file mode 100644 index 9e612858f8..0000000000 Binary files a/docs/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/docs/fonts/glyphicons-halflings-regular.woff2 b/docs/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100644 index 64539b54c3..0000000000 Binary files a/docs/fonts/glyphicons-halflings-regular.woff2 and /dev/null differ diff --git a/docs/images/favicon.ico b/docs/images/favicon.ico deleted file mode 100644 index 6580a70d75..0000000000 Binary files a/docs/images/favicon.ico and /dev/null differ diff --git a/docs/images/logo/pmd-logo-70px.png b/docs/images/logo/pmd-logo-70px.png new file mode 100644 index 0000000000..60da90c0e8 Binary files /dev/null and b/docs/images/logo/pmd-logo-70px.png differ diff --git a/docs/images/logo/pmd_logo.jpg b/docs/images/logo/pmd_logo.jpg deleted file mode 100644 index b94df4507f..0000000000 Binary files a/docs/images/logo/pmd_logo.jpg and /dev/null differ diff --git a/docs/images/logo/pmd_logo.png b/docs/images/logo/pmd_logo.png deleted file mode 100644 index bdff9acc56..0000000000 Binary files a/docs/images/logo/pmd_logo.png and /dev/null differ diff --git a/docs/images/logo/pmd_logo.svgz b/docs/images/logo/pmd_logo.svgz deleted file mode 100644 index 3250b51a59..0000000000 Binary files a/docs/images/logo/pmd_logo.svgz and /dev/null differ diff --git a/docs/images/logo/pmd_logo_small.jpg b/docs/images/logo/pmd_logo_small.jpg deleted file mode 100644 index a3a65423ea..0000000000 Binary files a/docs/images/logo/pmd_logo_small.jpg and /dev/null differ diff --git a/docs/images/logo/pmd_logo_small.png b/docs/images/logo/pmd_logo_small.png deleted file mode 100644 index fd0bfb0ad9..0000000000 Binary files a/docs/images/logo/pmd_logo_small.png and /dev/null differ diff --git a/docs/images/logo/pmd_logo_tiny.png b/docs/images/logo/pmd_logo_tiny.png deleted file mode 100644 index d7267fc392..0000000000 Binary files a/docs/images/logo/pmd_logo_tiny.png and /dev/null differ diff --git a/docs/images/pmd-logo-big.png b/docs/images/pmd-logo-big.png deleted file mode 100644 index bdff9acc56..0000000000 Binary files a/docs/images/pmd-logo-big.png and /dev/null differ diff --git a/docs/images/pmd-logo-small.png b/docs/images/pmd-logo-small.png deleted file mode 100644 index 3428347426..0000000000 Binary files a/docs/images/pmd-logo-small.png and /dev/null differ diff --git a/docs/images/pmd-logo.png b/docs/images/pmd-logo.png deleted file mode 100644 index 2428b3317e..0000000000 Binary files a/docs/images/pmd-logo.png and /dev/null differ diff --git a/docs/index.md b/docs/index.md index aa76696556..c143ec45ca 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,18 +10,15 @@ summary: > last_updated: August 2017 author: Jeff Jensen , Andreas Dangel , Clément Fournier + +additional_js: + - assets/Shuffle-5.2.3/dist/shuffle.min.js + - assets/jquery-ui-1.12.1/jquery-ui.min.js + - js/shuffle.js --- -{% unless site.output == "pdf" %} - - - -{% include custom/panel_scroll.html %} -{% endunless %} - - ## Overview @@ -76,7 +73,6 @@ you may also use the search bar in the top right, or the sidebar on the left. -
    @@ -92,7 +88,7 @@ you may also use the search bar in the top right, or the sidebar on the left. tags="rule_references" datagroups='["userdocs"]' description="Pick your language to find out about the rule it supports." - image="fa-database" + fa-icon="fa-database" titlemaker="page.language_name" %} {% include custom/shuffle_panel.html @@ -107,7 +103,7 @@ you may also use the search bar in the top right, or the sidebar on the left. tags="userdocs" except_tags="extending,tools" datagroups='["userdocs"]' - image="fa-cog" + fa-icon="fa-cog" description="Learn how to build effective and versatile rulesets." %} @@ -117,7 +113,8 @@ you may also use the search bar in the top right, or the sidebar on the left. tags="devdocs" except_tags="extending" datagroups='["contributing"]' - image="fa-github" + fa-style="fab" + fa-icon="fa-github" description="If you'd like to help us build PMD, these topics may interest you. See you around!" %} @@ -137,21 +134,11 @@ you may also use the search bar in the top right, or the sidebar on the left. description="" %} - - -
    - -
    + +
    -{% unless site.output == "pdf" %} - -{% include initialize_shuffle.html %} - -{% endunless %} - - {% include links.html %} diff --git a/docs/js/customscripts.js b/docs/js/customscripts.js index 8c9fb4cb9f..96aaa58cec 100644 --- a/docs/js/customscripts.js +++ b/docs/js/customscripts.js @@ -1,16 +1,16 @@ - -$('#mysidebar').height($(".nav").height()); - - $( document ).ready(function() { - //this script says, if the height of the viewport is greater than 800px, then insert affix class, which makes the nav bar float in a fixed - // position as your scroll. if you have a lot of nav items, this height may not work for you. + $('#mysidebar').height($(".nav").height()); + + // this script says, if the height of the viewport is greater than 800px, then insert position-fixed class, + // which makes the nav bar float in a fixed position as your scroll. If you have a lot of nav items, + // this height may not work for you. var h = $(window).height(); //console.log (h); if (h > 800) { - $( "#mysidebar" ).attr("class", "nav affix"); + $( "#mysidebar" ).attr("class", "nav position-fixed"); } + // activate tooltips. although this is a bootstrap js function, it must be activated this way in your theme. $('[data-toggle="tooltip"]').tooltip({ placement : 'top' @@ -21,35 +21,53 @@ $( document ).ready(function() { */ anchors.add('h2,h3,h4,h5'); -}); + // This highlights the active parent class in the navgoco sidebar. This is critical so that the parent expands + // when you're viewing a page. + // Note: the class needs to be added before navgoco is initialized. Navgoco uses then this information + // to expand the menus. + $("li.active").parents('li').toggleClass("active"); -// needed for nav tabs on pages. See Formatting > Nav tabs for more details. -// script from http://stackoverflow.com/questions/10523433/how-do-i-keep-the-current-tab-active-with-twitter-bootstrap-after-a-page-reload -$(function() { - var json, tabsState; - $('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) { - var href, json, parentId, tabsState; - - tabsState = localStorage.getItem("tabs-state"); - json = JSON.parse(tabsState || "{}"); - parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id"); - href = $(e.target).attr('href'); - json[parentId] = href; - - return localStorage.setItem("tabs-state", JSON.stringify(json)); - }); - - tabsState = localStorage.getItem("tabs-state"); - json = JSON.parse(tabsState || "{}"); - - $.each(json, function(containerId, href) { - return $("#" + containerId + " a[href=" + href + "]").tab('show'); - }); - - $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() { - var $this = $(this); - if (!json[$this.attr("id")]) { - return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show"); + // Initialize navgoco with default options + $("#mysidebar").navgoco({ + caretHtml: '', + accordion: true, + openClass: 'active', + save: false, + slide: { + duration: 400, + easing: 'swing' } }); + + // This handles the automatic toc. Use ## for subheads to auto-generate the on-page minitoc. + // If you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. + $('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' }); + + // Initialize jekyll search in topnav. + SimpleJekyllSearch.init({ + searchInput: document.getElementById('search-input'), + resultsContainer: document.getElementById('results-container'), + json: 'search.json', + searchResultTemplate: '
  • {title}
  • ', + noResultsText: '{{site.data.strings.search_no_results_text}}', + limit: 10, + fuzzy: true, + }); + // Make sure to close and empty the search results after clicking one result item. + // This is necessary, if we don't switch the page but only jump to a anchor on the + // same page. + $('#results-container').click(function() { + $('#search-input').val(''); + $(this).empty(); + }); + + // Topnav toggle button for displaying/hiding nav sidebar + $("#tg-sb-link").click(function(event) { + $("#tg-sb-sidebar").toggle(); + $("#tg-sb-content").toggleClass('col-md-9'); + $("#tg-sb-content").toggleClass('col-md-12'); + $("#tg-sb-icon").toggleClass('fa-toggle-on'); + $("#tg-sb-icon").toggleClass('fa-toggle-off'); + event.preventDefault(); + }); }); diff --git a/docs/js/jekyll-search.js b/docs/js/jekyll-search.js deleted file mode 100644 index 04d6a0d3a4..0000000000 --- a/docs/js/jekyll-search.js +++ /dev/null @@ -1 +0,0 @@ -!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o=0}var self=this;self.matches=function(string,crit){return"string"!=typeof string?!1:(string=string.trim(),doMatch(string,crit))}}module.exports=new LiteralSearchStrategy},{}],4:[function(require,module){module.exports=function(){function findMatches(store,crit,strategy){for(var data=store.get(),i=0;i{title}',noResultsText:"No results found",limit:10,fuzzy:!1};self.init=function(_opt){validateOptions(_opt),assignOptions(_opt),isJSON(opt.dataSource)?initWithJSON(opt.dataSource):initWithURL(opt.dataSource)}}var Searcher=require("./Searcher"),Templater=require("./Templater"),Store=require("./Store"),JSONLoader=require("./JSONLoader"),searcher=new Searcher,templater=new Templater,store=new Store,jsonLoader=new JSONLoader;window.SimpleJekyllSearch=new SimpleJekyllSearch}(window,document)},{"./JSONLoader":1,"./Searcher":4,"./Store":5,"./Templater":6}]},{},[7]); \ No newline at end of file diff --git a/docs/js/jquery-ui.min.js b/docs/js/jquery-ui.min.js deleted file mode 100644 index db0af4c4d5..0000000000 --- a/docs/js/jquery-ui.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2018-05-27 -* http://jqueryui.com -* Includes: effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e="ui-effects-",i="ui-effects-style",s="ui-effects-animated",n=t;t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=h(),n=s._rgba=[];return i=i.toLowerCase(),f(l,function(t,o){var a,r=o.re.exec(i),l=r&&o.parse(r),h=o.space||"rgba";return l?(a=s[h](l),s[c[h].cache]=a[c[h].cache],n=s._rgba=a._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,o.transparent),s):o[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var o,a="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,l=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],h=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=h.support={},p=t("

    ")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,a,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,l],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),o=c[n],a=0===this.alpha()?h("transparent"):this,r=a[o.cache]||o.to(a._rgba),l=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],h=s[o],c=u[n.type]||{};null!==h&&(null===a?l[o]=h:(c.mod&&(h-a>c.mod/2?a+=c.mod:a-h>c.mod/2&&(a-=c.mod)),l[o]=i((h-a)*e+a,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),l=Math.min(s,n,o),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-o)/h+360:n===r?60*(o-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[a]&&(this[a]=l(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[a]=d,n):h(d)},f(o,function(e,i){h.fn[e]||(h.fn[e]=function(n){var o,a=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=h(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(n),function(){function e(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function i(e,i){var s,n,a={};for(s in i)n=i[s],e[s]!==n&&(o[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(a[s]=n));return a}var s=["add","remove","toggle"],o={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(n.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(n,o,a,r){var l=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",h=l.children?a.find("*").addBack():a;h=h.map(function(){var i=t(this);return{el:i,start:e(this)}}),o=function(){t.each(s,function(t,e){n[e]&&a[e+"Class"](n[e])})},o(),h=h.map(function(){return this.end=e(this.el[0]),this.diff=i(this.start,this.end),this}),a.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(e){return function(i,s,n,o,a){return"boolean"==typeof s||void 0===s?n?t.effects.animateClass.call(this,s?{add:i}:{remove:i},n,o,a):e.apply(this,arguments):t.effects.animateClass.call(this,{toggle:i},s,n,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function n(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function o(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}function a(t,e){var i=e.outerWidth(),s=e.outerHeight(),n=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,o=n.exec(t)||["",0,i,s,0];return{top:parseFloat(o[1])||0,right:"auto"===o[2]?i:parseFloat(o[2]),bottom:"auto"===o[3]?s:parseFloat(o[3]),left:parseFloat(o[4])||0}}t.expr&&t.expr.filters&&t.expr.filters.animated&&(t.expr.filters.animated=function(e){return function(i){return!!t(i).data(s)||e(i)}}(t.expr.filters.animated)),t.uiBackCompat!==!1&&t.extend(t.effects,{save:function(t,i){for(var s=0,n=i.length;n>s;s++)null!==i[s]&&t.data(e+i[s],t[0].style[i[s]])},restore:function(t,i){for(var s,n=0,o=i.length;o>n;n++)null!==i[n]&&(s=t.data(e+i[n]),t.css(i[n],s))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("

    ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).trigger("focus"),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).trigger("focus")),e}}),t.extend(t.effects,{version:"1.12.1",define:function(e,i,s){return s||(s=i,i="effect"),t.effects.effect[e]=s,t.effects.effect[e].mode=i,s},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,n="vertical"!==i?(e||100)/100:1;return{height:t.height()*n,width:t.width()*s,outerHeight:t.outerHeight()*n,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();e>1&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(i,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(i)||"",t.removeData(i)},mode:function(t,e){var i=t.is(":hidden");return"toggle"===e&&(e=i?"show":"hide"),(i?"hide"===e:"show"===e)&&(e="none"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(i){var s,n=i.css("position"),o=i.position();return i.css({marginTop:i.css("marginTop"),marginBottom:i.css("marginBottom"),marginLeft:i.css("marginLeft"),marginRight:i.css("marginRight")}).outerWidth(i.outerWidth()).outerHeight(i.outerHeight()),/^(static|relative)/.test(n)&&(n="absolute",s=t("<"+i[0].nodeName+">").insertAfter(i).css({display:/^(inline|ruby)/.test(i.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:i.css("marginTop"),marginBottom:i.css("marginBottom"),marginLeft:i.css("marginLeft"),marginRight:i.css("marginRight"),"float":i.css("float")}).outerWidth(i.outerWidth()).outerHeight(i.outerHeight()).addClass("ui-effects-placeholder"),i.data(e+"placeholder",s)),i.css({position:n,left:o.left,top:o.top}),s},removePlaceholder:function(t){var i=e+"placeholder",s=t.data(i);s&&(s.remove(),t.removeData(i))},cleanUp:function(e){t.effects.restoreStyle(e),t.effects.removePlaceholder(e)},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function e(e){function n(){l.removeData(s),t.effects.cleanUp(l),"hide"===i.mode&&l.hide(),r()}function r(){t.isFunction(h)&&h.call(l[0]),t.isFunction(e)&&e()}var l=t(this);i.mode=u.shift(),t.uiBackCompat===!1||a?"none"===i.mode?(l[c](),r()):o.call(l[0],i,n):(l.is(":hidden")?"hide"===c:"show"===c)?(l[c](),r()):o.call(l[0],i,r)}var i=n.apply(this,arguments),o=t.effects.effect[i.effect],a=o.mode,r=i.queue,l=r||"fx",h=i.complete,c=i.mode,u=[],d=function(e){var i=t(this),n=t.effects.mode(i,c)||a;i.data(s,!0),u.push(n),a&&("show"===n||n===a&&"hide"===n)&&i.show(),a&&"none"===n||t.effects.saveStyle(i),t.isFunction(e)&&e()};return t.fx.off||!o?c?this[c](i.duration,h):this.each(function(){h&&h.call(this)}):r===!1?this.each(d).each(e):this.queue(l,d).queue(l,e)},show:function(t){return function(e){if(o(e))return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(o(e))return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(o(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=n.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):a(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,l=o?a.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("
    ").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-l,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=a(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var o=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},l=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),l&&l.css(t.effects.clipToBox(r)),r.clip=a),l&&l.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,l="hide"===r,h="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(h||l?1:0),f=e.duration/p,m=e.easing,g="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(g),u||(u=a["top"===g?"outerHeight":"outerWidth"]()/3),h&&(n={opacity:1},n[g]=o,a.css("opacity",0).css(g,_?2*-u:2*u).animate(n,f,m)),l&&(u/=Math.pow(2,d-1)),n={},n[g]=o;d>v;v++)s={},s[g]=(_?"-=":"+=")+u,a.animate(s,f,m).animate(n,f,m),u=l?2*u:u/2;l&&(s={opacity:0},s[g]=(_?"-=":"+=")+u,a.animate(s,f,m)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,l=r||"horizontal"===a,h=r||"vertical"===a;s=o.cssClip(),n.clip={top:h?(s.bottom-s.top)/2:s.top,right:l?(s.right-s.left)/2:s.right,bottom:h?(s.bottom-s.top)/2:s.bottom,left:l?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",l="up"===r||"down"===r?"top":"left",h="up"===r||"left"===r?"-=":"+=",c="+="===h?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,u[l]=h+s,a&&(n.css(u),u[l]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,m="show"===f,g=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(l=g.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=g.left+a*_,h=a-(d-1)/2,p.clone().appendTo("body").wrap("
    ").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(m?h*_:0),top:l+(m?c*v:0),opacity:m?0:1}).animate({left:r+(m?0:h*_),top:l+(m?0:c*v),opacity:m?1:0},e.duration||500,e.easing,s)}),t.effects.define("fade","toggle",function(e,i){var s="show"===e.mode;t(this).css("opacity",s?0:1).animate({opacity:s?1:0},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("fold","hide",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=e.size||15,l=/([0-9]+)%/.exec(r),h=!!e.horizFirst,c=h?["right","bottom"]:["bottom","right"],u=e.duration/2,d=t.effects.createPlaceholder(s),p=s.cssClip(),f={clip:t.extend({},p)},m={clip:t.extend({},p)},g=[p[c[0]],p[c[1]]],_=s.queue().length;l&&(r=parseInt(l[1],10)/100*g[a?0:1]),f.clip[c[0]]=r,m.clip[c[0]]=r,m.clip[c[1]]=0,o&&(s.cssClip(m.clip),d&&d.css(t.effects.clipToBox(m)),m.clip=p),s.queue(function(i){d&&d.animate(t.effects.clipToBox(f),u,e.easing).animate(t.effects.clipToBox(m),u,e.easing),i()}).animate(f,u,e.easing).animate(m,u,e.easing).queue(i),t.effects.unshift(s,_,4)}),t.effects.define("highlight","show",function(e,i){var s=t(this),n={backgroundColor:s.css("backgroundColor")};"hide"===e.mode&&(n.opacity=0),t.effects.saveStyle(s),s.css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("size",function(e,i){var s,n,o,a=t(this),r=["fontSize"],l=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.mode,u="effect"!==c,d=e.scale||"both",p=e.origin||["middle","center"],f=a.css("position"),m=a.position(),g=t.effects.scaledDimensions(a),_=e.from||g,v=e.to||t.effects.scaledDimensions(a,0);t.effects.createPlaceholder(a),"show"===c&&(o=_,_=v,v=o),n={from:{y:_.height/g.height,x:_.width/g.width},to:{y:v.height/g.height,x:v.width/g.width}},("box"===d||"both"===d)&&(n.from.y!==n.to.y&&(_=t.effects.setTransition(a,l,n.from.y,_),v=t.effects.setTransition(a,l,n.to.y,v)),n.from.x!==n.to.x&&(_=t.effects.setTransition(a,h,n.from.x,_),v=t.effects.setTransition(a,h,n.to.x,v))),("content"===d||"both"===d)&&n.from.y!==n.to.y&&(_=t.effects.setTransition(a,r,n.from.y,_),v=t.effects.setTransition(a,r,n.to.y,v)),p&&(s=t.effects.getBaseline(p,g),_.top=(g.outerHeight-_.outerHeight)*s.y+m.top,_.left=(g.outerWidth-_.outerWidth)*s.x+m.left,v.top=(g.outerHeight-v.outerHeight)*s.y+m.top,v.left=(g.outerWidth-v.outerWidth)*s.x+m.left),a.css(_),("content"===d||"both"===d)&&(l=l.concat(["marginTop","marginBottom"]).concat(r),h=h.concat(["marginLeft","marginRight"]),a.find("*[width]").each(function(){var i=t(this),s=t.effects.scaledDimensions(i),o={height:s.height*n.from.y,width:s.width*n.from.x,outerHeight:s.outerHeight*n.from.y,outerWidth:s.outerWidth*n.from.x},a={height:s.height*n.to.y,width:s.width*n.to.x,outerHeight:s.height*n.to.y,outerWidth:s.width*n.to.x};n.from.y!==n.to.y&&(o=t.effects.setTransition(i,l,n.from.y,o),a=t.effects.setTransition(i,l,n.to.y,a)),n.from.x!==n.to.x&&(o=t.effects.setTransition(i,h,n.from.x,o),a=t.effects.setTransition(i,h,n.to.x,a)),u&&t.effects.saveStyle(i),i.css(o),i.animate(a,e.duration,e.easing,function(){u&&t.effects.restoreStyle(i)})})),a.animate(v,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){var e=a.offset();0===v.opacity&&a.css("opacity",_.opacity),u||(a.css("position","static"===f?"relative":f).offset(e),t.effects.saveStyle(a)),i()}})}),t.effects.define("scale",function(e,i){var s=t(this),n=e.mode,o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"effect"!==n?0:100),a=t.extend(!0,{from:t.effects.scaledDimensions(s),to:t.effects.scaledDimensions(s,o,e.direction||"both"),origin:e.origin||["middle","center"]},e);e.fade&&(a.from.opacity=1,a.to.opacity=0),t.effects.effect.size.call(this,a,i)}),t.effects.define("puff","hide",function(e,i){var s=t.extend(!0,{},e,{fade:!0,percent:parseInt(e.percent,10)||150});t.effects.effect.scale.call(this,s,i)}),t.effects.define("pulsate","show",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=o||a,l=2*(e.times||5)+(r?1:0),h=e.duration/l,c=0,u=1,d=s.queue().length;for((o||!s.is(":visible"))&&(s.css("opacity",0).show(),c=1);l>u;u++)s.animate({opacity:c},h,e.easing),c=1-c;s.animate({opacity:c},h,e.easing),s.queue(i),t.effects.unshift(s,d,l+1)}),t.effects.define("shake",function(e,i){var s=1,n=t(this),o=e.direction||"left",a=e.distance||20,r=e.times||3,l=2*r+1,h=Math.round(e.duration/l),c="up"===o||"down"===o?"top":"left",u="up"===o||"left"===o,d={},p={},f={},m=n.queue().length;for(t.effects.createPlaceholder(n),d[c]=(u?"-=":"+=")+a,p[c]=(u?"+=":"-=")+2*a,f[c]=(u?"-=":"+=")+2*a,n.animate(d,h,e.easing);r>s;s++)n.animate(p,h,e.easing).animate(f,h,e.easing);n.animate(p,h,e.easing).animate(d,h/2,e.easing).queue(i),t.effects.unshift(n,m,l+1)}),t.effects.define("slide","show",function(e,i){var s,n,o=t(this),a={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},r=e.mode,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u=e.distance||o["top"===h?"outerHeight":"outerWidth"](!0),d={};t.effects.createPlaceholder(o),s=o.cssClip(),n=o.position()[h],d[h]=(c?-1:1)*u+n,d.clip=o.cssClip(),d.clip[a[l][1]]=d.clip[a[l][0]],"show"===r&&(o.cssClip(d.clip),o.css(h,d[h]),d.clip=s,d[h]=n),o.animate(d,{queue:!1,duration:e.duration,easing:e.easing,complete:i})});var o;t.uiBackCompat!==!1&&(o=t.effects.define("transfer",function(e,i){t(this).transfer(e,i)}))}); \ No newline at end of file diff --git a/docs/js/jquery.ba-throttle-debounce.min.js b/docs/js/jquery.ba-throttle-debounce.min.js deleted file mode 100644 index 07205508eb..0000000000 --- a/docs/js/jquery.ba-throttle-debounce.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - * jQuery throttle / debounce - v1.1 - 3/7/2010 - * http://benalman.com/projects/jquery-throttle-debounce-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ -(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this); \ No newline at end of file diff --git a/docs/js/jquery.localScroll.min.js b/docs/js/jquery.localScroll.min.js deleted file mode 100644 index 48a6e168f6..0000000000 --- a/docs/js/jquery.localScroll.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) 2007-2014 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com - * Licensed under MIT - * @author Ariel Flesler - * @version 1.3.5 - */ -;(function(a){if(typeof define==='function'&&define.amd){define(['jquery'],a)}else{a(jQuery)}}(function($){var g=location.href.replace(/#.*/,'');var h=$.localScroll=function(a){$('body').localScroll(a)};h.defaults={duration:1000,axis:'y',event:'click',stop:true,target:window};$.fn.localScroll=function(a){a=$.extend({},h.defaults,a);if(a.hash&&location.hash){if(a.target)window.scrollTo(0,0);scroll(0,location,a)}return a.lazy?this.on(a.event,'a,area',function(e){if(filter.call(this)){scroll(e,this,a)}}):this.find('a,area').filter(filter).bind(a.event,function(e){scroll(e,this,a)}).end().end();function filter(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==g&&(!a.filter||$(this).is(a.filter))}};h.hash=function(){};function scroll(e,a,b){var c=a.hash.slice(1),elem=document.getElementById(c)||document.getElementsByName(c)[0];if(!elem)return;if(e)e.preventDefault();var d=$(b.target);if(b.lock&&d.is(':animated')||b.onBefore&&b.onBefore(e,elem,d)===false)return;if(b.stop)d._scrollable().stop(true);if(b.hash){var f=elem.id===c?'id':'name',$a=$(' ').attr(f,c).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});elem[f]='';$('body').prepend($a);location.hash=a.hash;$a.remove();elem[f]=c}d.scrollTo(elem,b).trigger('notify.serialScroll',[elem])};return h})); \ No newline at end of file diff --git a/docs/js/jquery.scrollTo.min.js b/docs/js/jquery.scrollTo.min.js deleted file mode 100644 index d9f9b1599c..0000000000 --- a/docs/js/jquery.scrollTo.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) 2007-2014 Ariel Flesler - afleslergmailcom | http://flesler.blogspot.com - * Licensed under MIT - * @author Ariel Flesler - * @version 1.4.14 - */ -;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:0,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}})); \ No newline at end of file diff --git a/docs/js/jquery.shuffle.min.js b/docs/js/jquery.shuffle.min.js deleted file mode 100644 index d103127199..0000000000 --- a/docs/js/jquery.shuffle.min.js +++ /dev/null @@ -1,1588 +0,0 @@ -/*! - * Shuffle.js by @Vestride - * Categorize, sort, and filter a responsive grid of items. - * Dependencies: jQuery 1.9+, Modernizr 2.6.2+ - * @license MIT license - * @version 3.0.0 - */ - -/* Modernizr 2.6.2 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes - */ -window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a){var e=a[d];if(!C(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["­",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.csstransforms=function(){return!!F("transform")},q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return F("transition")};for(var G in q)y(q,G)&&(v=G.toLowerCase(),e[v]=q[G](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)y(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},z(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,e.prefixed=function(a,b,c){return b?F(a,b,c):F(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document); - -(function (factory) { - if (typeof define === 'function' && define.amd) { - define(['jquery', 'modernizr'], factory); - } else { - window.Shuffle = factory(window.jQuery, window.Modernizr); - } -})(function($, Modernizr, undefined) { - -'use strict'; - - -// Validate Modernizr exists. -// Shuffle requires `csstransitions`, `csstransforms`, `csstransforms3d`, -// and `prefixed` to exist on the Modernizr object. -if (typeof Modernizr !== 'object') { - throw new Error('Shuffle.js requires Modernizr.\n' + - 'http://vestride.github.io/Shuffle/#dependencies'); -} - - -/** - * Returns css prefixed properties like `-webkit-transition` or `box-sizing` - * from `transition` or `boxSizing`, respectively. - * @param {(string|boolean)} prop Property to be prefixed. - * @return {string} The prefixed css property. - */ -function dashify( prop ) { - if (!prop) { - return ''; - } - - // Replace upper case with dash-lowercase, - // then fix ms- prefixes because they're not capitalized. - return prop.replace(/([A-Z])/g, function( str, m1 ) { - return '-' + m1.toLowerCase(); - }).replace(/^ms-/,'-ms-'); -} - -// Constant, prefixed variables. -var TRANSITION = Modernizr.prefixed('transition'); -var TRANSITION_DELAY = Modernizr.prefixed('transitionDelay'); -var TRANSITION_DURATION = Modernizr.prefixed('transitionDuration'); - -// Note(glen): Stock Android 4.1.x browser will fail here because it wrongly -// says it supports non-prefixed transitions. -// https://github.com/Modernizr/Modernizr/issues/897 -var TRANSITIONEND = { - 'WebkitTransition' : 'webkitTransitionEnd', - 'transition' : 'transitionend' -}[ TRANSITION ]; - -var TRANSFORM = Modernizr.prefixed('transform'); -var CSS_TRANSFORM = dashify(TRANSFORM); - -// Constants -var CAN_TRANSITION_TRANSFORMS = Modernizr.csstransforms && Modernizr.csstransitions; -var HAS_TRANSFORMS_3D = Modernizr.csstransforms3d; -var SHUFFLE = 'shuffle'; -var COLUMN_THRESHOLD = 0.3; - -// Configurable. You can change these constants to fit your application. -// The default scale and concealed scale, however, have to be different values. -var ALL_ITEMS = 'all'; -var FILTER_ATTRIBUTE_KEY = 'groups'; -var DEFAULT_SCALE = 1; -var CONCEALED_SCALE = 0.001; - - -// Underscore's throttle function. -function throttle(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - options = options || {}; - var later = function() { - previous = options.leading === false ? 0 : $.now(); - timeout = null; - result = func.apply(context, args); - context = args = null; - }; - return function() { - var now = $.now(); - if (!previous && options.leading === false) { - previous = now; - } - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; -} - -function each(obj, iterator, context) { - for (var i = 0, length = obj.length; i < length; i++) { - if (iterator.call(context, obj[i], i, obj) === {}) { - return; - } - } -} - -function defer(fn, context, wait) { - return setTimeout( $.proxy( fn, context ), wait ); -} - -function arrayMax( array ) { - return Math.max.apply( Math, array ); -} - -function arrayMin( array ) { - return Math.min.apply( Math, array ); -} - - -/** - * Always returns a numeric value, given a value. - * @param {*} value Possibly numeric value. - * @return {number} `value` or zero if `value` isn't numeric. - * @private - */ -function getNumber(value) { - return $.isNumeric(value) ? value : 0; -} - - -/** - * Represents a coordinate pair. - * @param {number} [x=0] X. - * @param {number} [y=0] Y. - */ -var Point = function(x, y) { - this.x = getNumber( x ); - this.y = getNumber( y ); -}; - - -/** - * Whether two points are equal. - * @param {Point} a Point A. - * @param {Point} b Point B. - * @return {boolean} - */ -Point.equals = function(a, b) { - return a.x === b.x && a.y === b.y; -}; - - -// Used for unique instance variables -var id = 0; -var $window = $( window ); - - -/** - * Categorize, sort, and filter a responsive grid of items. - * - * @param {Element} element An element which is the parent container for the grid items. - * @param {Object} [options=Shuffle.options] Options object. - * @constructor - */ -var Shuffle = function( element, options ) { - options = options || {}; - $.extend( this, Shuffle.options, options, Shuffle.settings ); - - this.$el = $(element); - this.element = element; - this.unique = 'shuffle_' + id++; - - this._fire( Shuffle.EventType.LOADING ); - this._init(); - - // Dispatch the done event asynchronously so that people can bind to it after - // Shuffle has been initialized. - defer(function() { - this.initialized = true; - this._fire( Shuffle.EventType.DONE ); - }, this, 16); -}; - - -/** - * Events the container element emits with the .shuffle namespace. - * For example, "done.shuffle". - * @enum {string} - */ -Shuffle.EventType = { - LOADING: 'loading', - DONE: 'done', - LAYOUT: 'layout', - REMOVED: 'removed' -}; - - -/** @enum {string} */ -Shuffle.ClassName = { - BASE: SHUFFLE, - SHUFFLE_ITEM: 'shuffle-item', - FILTERED: 'filtered', - CONCEALED: 'concealed' -}; - - -// Overrideable options -Shuffle.options = { - group: ALL_ITEMS, // Initial filter group. - speed: 250, // Transition/animation speed (milliseconds). - easing: 'ease-out', // CSS easing function to use. - itemSelector: '', // e.g. '.picture-item'. - sizer: null, // Sizer element. Use an element to determine the size of columns and gutters. - gutterWidth: 0, // A static number or function that tells the plugin how wide the gutters between columns are (in pixels). - columnWidth: 0, // A static number or function that returns a number which tells the plugin how wide the columns are (in pixels). - delimeter: null, // If your group is not json, and is comma delimeted, you could set delimeter to ','. - buffer: 0, // Useful for percentage based heights when they might not always be exactly the same (in pixels). - initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method. - throttle: throttle, // By default, shuffle will throttle resize events. This can be changed or removed. - throttleTime: 300, // How often shuffle can be called on resize (in milliseconds). - sequentialFadeDelay: 150, // Delay between each item that fades in when adding items. - supported: CAN_TRANSITION_TRANSFORMS // Whether to use transforms or absolute positioning. -}; - - -// Not overrideable -Shuffle.settings = { - useSizer: false, - itemCss : { // default CSS for each item - position: 'absolute', - top: 0, - left: 0, - visibility: 'visible' - }, - revealAppendedDelay: 300, - lastSort: {}, - lastFilter: ALL_ITEMS, - enabled: true, - destroyed: false, - initialized: false, - _animations: [], - styleQueue: [] -}; - - -// Expose for testing. -Shuffle.Point = Point; - - -/** - * Static methods. - */ - -/** - * If the browser has 3d transforms available, build a string with those, - * otherwise use 2d transforms. - * @param {Point} point X and Y positions. - * @param {number} scale Scale amount. - * @return {string} A normalized string which can be used with the transform style. - * @private - */ -Shuffle._getItemTransformString = function(point, scale) { - if ( HAS_TRANSFORMS_3D ) { - return 'translate3d(' + point.x + 'px, ' + point.y + 'px, 0) scale3d(' + scale + ', ' + scale + ', 1)'; - } else { - return 'translate(' + point.x + 'px, ' + point.y + 'px) scale(' + scale + ')'; - } -}; - - -/** - * Retrieve the computed style for an element, parsed as a float. This should - * not be used for width or height values because jQuery mangles them and they - * are not precise enough. - * @param {Element} element Element to get style for. - * @param {string} style Style property. - * @return {number} The parsed computed value or zero if that fails because IE - * will return 'auto' when the element doesn't have margins instead of - * the computed style. - * @private - */ -Shuffle._getNumberStyle = function( element, style ) { - return Shuffle._getFloat( $( element ).css( style ) ); -}; - - -/** - * Parse a string as an integer. - * @param {string} value String integer. - * @return {number} The string as an integer or zero. - * @private - */ -Shuffle._getInt = function(value) { - return getNumber( parseInt( value, 10 ) ); -}; - -/** - * Parse a string as an float. - * @param {string} value String float. - * @return {number} The string as an float or zero. - * @private - */ -Shuffle._getFloat = function(value) { - return getNumber( parseFloat( value ) ); -}; - - -/** - * Returns the outer width of an element, optionally including its margins. - * The `offsetWidth` property must be used because having a scale transform - * on the element affects the bounding box. Sadly, Firefox doesn't return an - * integer value for offsetWidth (yet). - * @param {Element} element The element. - * @param {boolean} [includeMargins] Whether to include margins. Default is false. - * @return {number} The width. - */ -Shuffle._getOuterWidth = function( element, includeMargins ) { - var width = element.offsetWidth; - - // Use jQuery here because it uses getComputedStyle internally and is - // cross-browser. Using the style property of the element will only work - // if there are inline styles. - if ( includeMargins ) { - var marginLeft = Shuffle._getNumberStyle( element, 'marginLeft'); - var marginRight = Shuffle._getNumberStyle( element, 'marginRight'); - width += marginLeft + marginRight; - } - - return width; -}; - - -/** - * Returns the outer height of an element, optionally including its margins. - * @param {Element} element The element. - * @param {boolean} [includeMargins] Whether to include margins. Default is false. - * @return {number} The height. - */ -Shuffle._getOuterHeight = function( element, includeMargins ) { - var height = element.offsetHeight; - - if ( includeMargins ) { - var marginTop = Shuffle._getNumberStyle( element, 'marginTop'); - var marginBottom = Shuffle._getNumberStyle( element, 'marginBottom'); - height += marginTop + marginBottom; - } - - return height; -}; - - -/** - * Change a property or execute a function which will not have a transition - * @param {Element} element DOM element that won't be transitioned - * @param {Function} callback A function which will be called while transition - * is set to 0ms. - * @param {Object} [context] Optional context for the callback function. - * @private - */ -Shuffle._skipTransition = function( element, callback, context ) { - var duration = element.style[ TRANSITION_DURATION ]; - - // Set the duration to zero so it happens immediately - element.style[ TRANSITION_DURATION ] = '0ms'; // ms needed for firefox! - - callback.call( context ); - - // Force reflow - var reflow = element.offsetWidth; - // Avoid jshint warnings: unused variables and expressions. - reflow = null; - - // Put the duration back - element.style[ TRANSITION_DURATION ] = duration; -}; - - -/** - * Instance methods. - */ - -Shuffle.prototype._init = function() { - this.$items = this._getItems(); - - this.sizer = this._getElementOption( this.sizer ); - - if ( this.sizer ) { - this.useSizer = true; - } - - // Add class and invalidate styles - this.$el.addClass( Shuffle.ClassName.BASE ); - - // Set initial css for each item - this._initItems(); - - // Bind resize events - // http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer - $window.on('resize.' + SHUFFLE + '.' + this.unique, this._getResizeFunction()); - - // Get container css all in one request. Causes reflow - var containerCSS = this.$el.css(['position', 'overflow']); - var containerWidth = Shuffle._getOuterWidth( this.element ); - - // Add styles to the container if it doesn't have them. - this._validateStyles( containerCSS ); - - // We already got the container's width above, no need to cause another reflow getting it again... - // Calculate the number of columns there will be - this._setColumns( containerWidth ); - - // Kick off! - this.shuffle( this.group, this.initialSort ); - - // The shuffle items haven't had transitions set on them yet - // so the user doesn't see the first layout. Set them now that the first layout is done. - if ( this.supported ) { - defer(function() { - this._setTransitions(); - this.element.style[ TRANSITION ] = 'height ' + this.speed + 'ms ' + this.easing; - }, this); - } -}; - - -/** - * Returns a throttled and proxied function for the resize handler. - * @return {Function} - * @private - */ -Shuffle.prototype._getResizeFunction = function() { - var resizeFunction = $.proxy( this._onResize, this ); - return this.throttle ? - this.throttle( resizeFunction, this.throttleTime ) : - resizeFunction; -}; - - -/** - * Retrieve an element from an option. - * @param {string|jQuery|Element} option The option to check. - * @return {?Element} The plain element or null. - * @private - */ -Shuffle.prototype._getElementOption = function( option ) { - // If column width is a string, treat is as a selector and search for the - // sizer element within the outermost container - if ( typeof option === 'string' ) { - return this.$el.find( option )[0] || null; - - // Check for an element - } else if ( option && option.nodeType && option.nodeType === 1 ) { - return option; - - // Check for jQuery object - } else if ( option && option.jquery ) { - return option[0]; - } - - return null; -}; - - -/** - * Ensures the shuffle container has the css styles it needs applied to it. - * @param {Object} styles Key value pairs for position and overflow. - * @private - */ -Shuffle.prototype._validateStyles = function(styles) { - // Position cannot be static. - if ( styles.position === 'static' ) { - this.element.style.position = 'relative'; - } - - // Overflow has to be hidden - if ( styles.overflow !== 'hidden' ) { - this.element.style.overflow = 'hidden'; - } -}; - - -/** - * Filter the elements by a category. - * @param {string} [category] Category to filter by. If it's given, the last - * category will be used to filter the items. - * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to - * all the items. - * @return {jQuery} Filtered items. - * @private - */ -Shuffle.prototype._filter = function( category, $collection ) { - category = category || this.lastFilter; - $collection = $collection || this.$items; - - var set = this._getFilteredSets( category, $collection ); - - // Individually add/remove concealed/filtered classes - this._toggleFilterClasses( set.filtered, set.concealed ); - - // Save the last filter in case elements are appended. - this.lastFilter = category; - - // This is saved mainly because providing a filter function (like searching) - // will overwrite the `lastFilter` property every time its called. - if ( typeof category === 'string' ) { - this.group = category; - } - - return set.filtered; -}; - - -/** - * Returns an object containing the filtered and concealed elements. - * @param {string|Function} category Category or function to filter by. - * @param {ArrayLike.} $items A collection of items to filter. - * @return {!{filtered: jQuery, concealed: jQuery}} - * @private - */ -Shuffle.prototype._getFilteredSets = function( category, $items ) { - var $filtered = $(); - var $concealed = $(); - - // category === 'all', add filtered class to everything - if ( category === ALL_ITEMS ) { - $filtered = $items; - - // Loop through each item and use provided function to determine - // whether to hide it or not. - } else { - each($items, function( el ) { - var $item = $(el); - if ( this._doesPassFilter( category, $item ) ) { - $filtered = $filtered.add( $item ); - } else { - $concealed = $concealed.add( $item ); - } - }, this); - } - - return { - filtered: $filtered, - concealed: $concealed - }; -}; - - -/** - * Test an item to see if it passes a category. - * @param {string|Function} category Category or function to filter by. - * @param {jQuery} $item A single item, wrapped with jQuery. - * @return {boolean} Whether it passes the category/filter. - * @private - */ -Shuffle.prototype._doesPassFilter = function( category, $item ) { - if ( $.isFunction( category ) ) { - return category.call( $item[0], $item, this ); - - // Check each element's data-groups attribute against the given category. - } else { - var groups = $item.data( FILTER_ATTRIBUTE_KEY ); - var keys = this.delimeter && !$.isArray( groups ) ? - groups.split( this.delimeter ) : - groups; - return $.inArray(category, keys) > -1; - } -}; - - -/** - * Toggles the filtered and concealed class names. - * @param {jQuery} $filtered Filtered set. - * @param {jQuery} $concealed Concealed set. - * @private - */ -Shuffle.prototype._toggleFilterClasses = function( $filtered, $concealed ) { - $filtered - .removeClass( Shuffle.ClassName.CONCEALED ) - .addClass( Shuffle.ClassName.FILTERED ); - $concealed - .removeClass( Shuffle.ClassName.FILTERED ) - .addClass( Shuffle.ClassName.CONCEALED ); -}; - - -/** - * Set the initial css for each item - * @param {jQuery} [$items] Optionally specifiy at set to initialize - */ -Shuffle.prototype._initItems = function( $items ) { - $items = $items || this.$items; - $items.addClass([ - Shuffle.ClassName.SHUFFLE_ITEM, - Shuffle.ClassName.FILTERED - ].join(' ')); - $items.css( this.itemCss ).data('point', new Point()).data('scale', DEFAULT_SCALE); -}; - - -/** - * Updates the filtered item count. - * @private - */ -Shuffle.prototype._updateItemCount = function() { - this.visibleItems = this._getFilteredItems().length; -}; - - -/** - * Sets css transform transition on a an element. - * @param {Element} element Element to set transition on. - * @private - */ -Shuffle.prototype._setTransition = function( element ) { - element.style[ TRANSITION ] = CSS_TRANSFORM + ' ' + this.speed + 'ms ' + - this.easing + ', opacity ' + this.speed + 'ms ' + this.easing; -}; - - -/** - * Sets css transform transition on a group of elements. - * @param {ArrayLike.} $items Elements to set transitions on. - * @private - */ -Shuffle.prototype._setTransitions = function( $items ) { - $items = $items || this.$items; - each($items, function( el ) { - this._setTransition( el ); - }, this); -}; - - -/** - * Sets a transition delay on a collection of elements, making each delay - * greater than the last. - * @param {ArrayLike.} $collection Array to iterate over. - */ -Shuffle.prototype._setSequentialDelay = function( $collection ) { - if ( !this.supported ) { - return; - } - - // $collection can be an array of dom elements or jquery object - each($collection, function( el, i ) { - // This works because the transition-property: transform, opacity; - el.style[ TRANSITION_DELAY ] = '0ms,' + ((i + 1) * this.sequentialFadeDelay) + 'ms'; - }, this); -}; - - -Shuffle.prototype._getItems = function() { - return this.$el.children( this.itemSelector ); -}; - - -Shuffle.prototype._getFilteredItems = function() { - return this.$items.filter('.' + Shuffle.ClassName.FILTERED); -}; - - -Shuffle.prototype._getConcealedItems = function() { - return this.$items.filter('.' + Shuffle.ClassName.CONCEALED); -}; - - -/** - * Returns the column size, based on column width and sizer options. - * @param {number} containerWidth Size of the parent container. - * @param {number} gutterSize Size of the gutters. - * @return {number} - * @private - */ -Shuffle.prototype._getColumnSize = function( containerWidth, gutterSize ) { - var size; - - // If the columnWidth property is a function, then the grid is fluid - if ( $.isFunction( this.columnWidth ) ) { - size = this.columnWidth(containerWidth); - - // columnWidth option isn't a function, are they using a sizing element? - } else if ( this.useSizer ) { - size = Shuffle._getOuterWidth(this.sizer); - - // if not, how about the explicitly set option? - } else if ( this.columnWidth ) { - size = this.columnWidth; - - // or use the size of the first item - } else if ( this.$items.length > 0 ) { - size = Shuffle._getOuterWidth(this.$items[0], true); - - // if there's no items, use size of container - } else { - size = containerWidth; - } - - // Don't let them set a column width of zero. - if ( size === 0 ) { - size = containerWidth; - } - - return size + gutterSize; -}; - - -/** - * Returns the gutter size, based on gutter width and sizer options. - * @param {number} containerWidth Size of the parent container. - * @return {number} - * @private - */ -Shuffle.prototype._getGutterSize = function( containerWidth ) { - var size; - if ( $.isFunction( this.gutterWidth ) ) { - size = this.gutterWidth(containerWidth); - } else if ( this.useSizer ) { - size = Shuffle._getNumberStyle(this.sizer, 'marginLeft'); - } else { - size = this.gutterWidth; - } - - return size; -}; - - -/** - * Calculate the number of columns to be used. Gets css if using sizer element. - * @param {number} [theContainerWidth] Optionally specify a container width if it's already available. - */ -Shuffle.prototype._setColumns = function( theContainerWidth ) { - var containerWidth = theContainerWidth || Shuffle._getOuterWidth( this.element ); - var gutter = this._getGutterSize( containerWidth ); - var columnWidth = this._getColumnSize( containerWidth, gutter ); - var calculatedColumns = (containerWidth + gutter) / columnWidth; - - // Widths given from getComputedStyle are not precise enough... - if ( Math.abs(Math.round(calculatedColumns) - calculatedColumns) < COLUMN_THRESHOLD ) { - // e.g. calculatedColumns = 11.998876 - calculatedColumns = Math.round( calculatedColumns ); - } - - this.cols = Math.max( Math.floor(calculatedColumns), 1 ); - this.containerWidth = containerWidth; - this.colWidth = columnWidth; -}; - -/** - * Adjust the height of the grid - */ -Shuffle.prototype._setContainerSize = function() { - this.$el.css( 'height', this._getContainerSize() ); -}; - - -/** - * Based on the column heights, it returns the biggest one. - * @return {number} - * @private - */ -Shuffle.prototype._getContainerSize = function() { - return arrayMax( this.positions ); -}; - - -/** - * Fire events with .shuffle namespace - */ -Shuffle.prototype._fire = function( name, args ) { - this.$el.trigger( name + '.' + SHUFFLE, args && args.length ? args : [ this ] ); -}; - - -/** - * Zeros out the y columns array, which is used to determine item placement. - * @private - */ -Shuffle.prototype._resetCols = function() { - var i = this.cols; - this.positions = []; - while (i--) { - this.positions.push( 0 ); - } -}; - - -/** - * Loops through each item that should be shown and calculates the x, y position. - * @param {Array.} items Array of items that will be shown/layed out in order in their array. - * Because jQuery collection are always ordered in DOM order, we can't pass a jq collection. - * @param {boolean} [isOnlyPosition=false] If true this will position the items with zero opacity. - */ -Shuffle.prototype._layout = function( items, isOnlyPosition ) { - each(items, function( item ) { - this._layoutItem( item, !!isOnlyPosition ); - }, this); - - // `_layout` always happens after `_shrink`, so it's safe to process the style - // queue here with styles from the shrink method. - this._processStyleQueue(); - - // Adjust the height of the container. - this._setContainerSize(); -}; - - -/** - * Calculates the position of the item and pushes it onto the style queue. - * @param {Element} item Element which is being positioned. - * @param {boolean} isOnlyPosition Whether to position the item, but with zero - * opacity so that it can fade in later. - * @private - */ -Shuffle.prototype._layoutItem = function( item, isOnlyPosition ) { - var $item = $(item); - var itemData = $item.data(); - var currPos = itemData.point; - var currScale = itemData.scale; - var itemSize = { - width: Shuffle._getOuterWidth( item, true ), - height: Shuffle._getOuterHeight( item, true ) - }; - var pos = this._getItemPosition( itemSize ); - - // If the item will not change its position, do not add it to the render - // queue. Transitions don't fire when setting a property to the same value. - if ( Point.equals(currPos, pos) && currScale === DEFAULT_SCALE ) { - return; - } - - // Save data for shrink - itemData.point = pos; - itemData.scale = DEFAULT_SCALE; - - this.styleQueue.push({ - $item: $item, - point: pos, - scale: DEFAULT_SCALE, - opacity: isOnlyPosition ? 0 : 1, - skipTransition: isOnlyPosition, - callfront: function() { - if ( !isOnlyPosition ) { - $item.css( 'visibility', 'visible' ); - } - }, - callback: function() { - if ( isOnlyPosition ) { - $item.css( 'visibility', 'hidden' ); - } - } - }); -}; - - -/** - * Determine the location of the next item, based on its size. - * @param {{width: number, height: number}} itemSize Object with width and height. - * @return {Point} - * @private - */ -Shuffle.prototype._getItemPosition = function( itemSize ) { - var columnSpan = this._getColumnSpan( itemSize.width, this.colWidth, this.cols ); - - var setY = this._getColumnSet( columnSpan, this.cols ); - - // Finds the index of the smallest number in the set. - var shortColumnIndex = this._getShortColumn( setY, this.buffer ); - - // Position the item - var point = new Point( - Math.round( this.colWidth * shortColumnIndex ), - Math.round( setY[shortColumnIndex] )); - - // Update the columns array with the new values for each column. - // e.g. before the update the columns could be [250, 0, 0, 0] for an item - // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0]. - var setHeight = setY[shortColumnIndex] + itemSize.height; - var setSpan = this.cols + 1 - setY.length; - for ( var i = 0; i < setSpan; i++ ) { - this.positions[ shortColumnIndex + i ] = setHeight; - } - - return point; -}; - - -/** - * Determine the number of columns an items spans. - * @param {number} itemWidth Width of the item. - * @param {number} columnWidth Width of the column (includes gutter). - * @param {number} columns Total number of columns - * @return {number} - * @private - */ -Shuffle.prototype._getColumnSpan = function( itemWidth, columnWidth, columns ) { - var columnSpan = itemWidth / columnWidth; - - // If the difference between the rounded column span number and the - // calculated column span number is really small, round the number to - // make it fit. - if ( Math.abs(Math.round( columnSpan ) - columnSpan ) < COLUMN_THRESHOLD ) { - // e.g. columnSpan = 4.0089945390298745 - columnSpan = Math.round( columnSpan ); - } - - // Ensure the column span is not more than the amount of columns in the whole layout. - return Math.min( Math.ceil( columnSpan ), columns ); -}; - - -/** - * Retrieves the column set to use for placement. - * @param {number} columnSpan The number of columns this current item spans. - * @param {number} columns The total columns in the grid. - * @return {Array.} An array of numbers represeting the column set. - * @private - */ -Shuffle.prototype._getColumnSet = function( columnSpan, columns ) { - // The item spans only one column. - if ( columnSpan === 1 ) { - return this.positions; - - // The item spans more than one column, figure out how many different - // places it could fit horizontally. - // The group count is the number of places within the positions this block - // could fit, ignoring the current positions of items. - // Imagine a 2 column brick as the second item in a 4 column grid with - // 10px height each. Find the places it would fit: - // [10, 0, 0, 0] - // | | | - // * * * - // - // Then take the places which fit and get the bigger of the two: - // max([10, 0]), max([0, 0]), max([0, 0]) = [10, 0, 0] - // - // Next, find the first smallest number (the short column). - // [10, 0, 0] - // | - // * - // - // And that's where it should be placed! - } else { - var groupCount = columns + 1 - columnSpan; - var groupY = []; - - // For how many possible positions for this item there are. - for ( var i = 0; i < groupCount; i++ ) { - // Find the bigger value for each place it could fit. - groupY[i] = arrayMax( this.positions.slice( i, i + columnSpan ) ); - } - - return groupY; - } -}; - - -/** - * Find index of short column, the first from the left where this item will go. - * - * @param {Array.} positions The array to search for the smallest number. - * @param {number} buffer Optional buffer which is very useful when the height - * is a percentage of the width. - * @return {number} Index of the short column. - * @private - */ -Shuffle.prototype._getShortColumn = function( positions, buffer ) { - var minPosition = arrayMin( positions ); - for (var i = 0, len = positions.length; i < len; i++) { - if ( positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer ) { - return i; - } - } - return 0; -}; - - -/** - * Hides the elements that don't match our filter. - * @param {jQuery} $collection jQuery collection to shrink. - * @private - */ -Shuffle.prototype._shrink = function( $collection ) { - var $concealed = $collection || this._getConcealedItems(); - - each($concealed, function( item ) { - var $item = $(item); - var itemData = $item.data(); - - // Continuing would add a transitionend event listener to the element, but - // that listener would not execute because the transform and opacity would - // stay the same. - if ( itemData.scale === CONCEALED_SCALE ) { - return; - } - - itemData.scale = CONCEALED_SCALE; - - this.styleQueue.push({ - $item: $item, - point: itemData.point, - scale : CONCEALED_SCALE, - opacity: 0, - callback: function() { - $item.css( 'visibility', 'hidden' ); - } - }); - }, this); -}; - - -/** - * Resize handler. - * @private - */ -Shuffle.prototype._onResize = function() { - // If shuffle is disabled, destroyed, don't do anything - if ( !this.enabled || this.destroyed || this.isTransitioning ) { - return; - } - - // Will need to check height in the future if it's layed out horizontaly - var containerWidth = Shuffle._getOuterWidth( this.element ); - - // containerWidth hasn't changed, don't do anything - if ( containerWidth === this.containerWidth ) { - return; - } - - this.update(); -}; - - -/** - * Returns styles for either jQuery animate or transition. - * @param {Object} opts Transition options. - * @return {!Object} Transforms for transitions, left/top for animate. - * @private - */ -Shuffle.prototype._getStylesForTransition = function( opts ) { - var styles = { - opacity: opts.opacity - }; - - if ( this.supported ) { - styles[ TRANSFORM ] = Shuffle._getItemTransformString( opts.point, opts.scale ); - } else { - styles.left = opts.point.x; - styles.top = opts.point.y; - } - - return styles; -}; - - -/** - * Transitions an item in the grid - * - * @param {Object} opts options. - * @param {jQuery} opts.$item jQuery object representing the current item. - * @param {Point} opts.point A point object with the x and y coordinates. - * @param {number} opts.scale Amount to scale the item. - * @param {number} opts.opacity Opacity of the item. - * @param {Function} opts.callback Complete function for the animation. - * @param {Function} opts.callfront Function to call before transitioning. - * @private - */ -Shuffle.prototype._transition = function( opts ) { - var styles = this._getStylesForTransition( opts ); - this._startItemAnimation( opts.$item, styles, opts.callfront || $.noop, opts.callback || $.noop ); -}; - - -Shuffle.prototype._startItemAnimation = function( $item, styles, callfront, callback ) { - // Transition end handler removes its listener. - function handleTransitionEnd( evt ) { - // Make sure this event handler has not bubbled up from a child. - if ( evt.target === evt.currentTarget ) { - $( evt.target ).off( TRANSITIONEND, handleTransitionEnd ); - callback(); - } - } - - callfront(); - - // Transitions are not set until shuffle has loaded to avoid the initial transition. - if ( !this.initialized ) { - $item.css( styles ); - callback(); - return; - } - - // Use CSS Transforms if we have them - if ( this.supported ) { - $item.css( styles ); - $item.on( TRANSITIONEND, handleTransitionEnd ); - - // Use jQuery to animate left/top - } else { - // Save the deferred object which jQuery returns. - var anim = $item.stop( true ).animate( styles, this.speed, 'swing', callback ); - // Push the animation to the list of pending animations. - this._animations.push( anim.promise() ); - } -}; - - -/** - * Execute the styles gathered in the style queue. This applies styles to elements, - * triggering transitions. - * @param {boolean} noLayout Whether to trigger a layout event. - * @private - */ -Shuffle.prototype._processStyleQueue = function( noLayout ) { - var $transitions = $(); - - // Iterate over the queue and keep track of ones that use transitions. - each(this.styleQueue, function( transitionObj ) { - if ( transitionObj.skipTransition ) { - this._styleImmediately( transitionObj ); - } else { - $transitions = $transitions.add( transitionObj.$item ); - this._transition( transitionObj ); - } - }, this); - - - if ( $transitions.length > 0 && this.initialized ) { - // Set flag that shuffle is currently in motion. - this.isTransitioning = true; - - if ( this.supported ) { - this._whenCollectionDone( $transitions, TRANSITIONEND, this._movementFinished ); - - // The _transition function appends a promise to the animations array. - // When they're all complete, do things. - } else { - this._whenAnimationsDone( this._movementFinished ); - } - - // A call to layout happened, but none of the newly filtered items will - // change position. Asynchronously fire the callback here. - } else if ( !noLayout ) { - defer( this._layoutEnd, this ); - } - - // Remove everything in the style queue - this.styleQueue.length = 0; -}; - - -/** - * Apply styles without a transition. - * @param {Object} opts Transitions options object. - * @private - */ -Shuffle.prototype._styleImmediately = function( opts ) { - Shuffle._skipTransition(opts.$item[0], function() { - opts.$item.css( this._getStylesForTransition( opts ) ); - }, this); -}; - -Shuffle.prototype._movementFinished = function() { - this.isTransitioning = false; - this._layoutEnd(); -}; - -Shuffle.prototype._layoutEnd = function() { - this._fire( Shuffle.EventType.LAYOUT ); -}; - -Shuffle.prototype._addItems = function( $newItems, addToEnd, isSequential ) { - // Add classes and set initial positions. - this._initItems( $newItems ); - - // Add transition to each item. - this._setTransitions( $newItems ); - - // Update the list of - this.$items = this._getItems(); - - // Shrink all items (without transitions). - this._shrink( $newItems ); - each(this.styleQueue, function( transitionObj ) { - transitionObj.skipTransition = true; - }); - - // Apply shrink positions, but do not cause a layout event. - this._processStyleQueue( true ); - - if ( addToEnd ) { - this._addItemsToEnd( $newItems, isSequential ); - } else { - this.shuffle( this.lastFilter ); - } -}; - - -Shuffle.prototype._addItemsToEnd = function( $newItems, isSequential ) { - // Get ones that passed the current filter - var $passed = this._filter( null, $newItems ); - var passed = $passed.get(); - - // How many filtered elements? - this._updateItemCount(); - - this._layout( passed, true ); - - if ( isSequential && this.supported ) { - this._setSequentialDelay( passed ); - } - - this._revealAppended( passed ); -}; - - -/** - * Triggers appended elements to fade in. - * @param {ArrayLike.} $newFilteredItems Collection of elements. - * @private - */ -Shuffle.prototype._revealAppended = function( newFilteredItems ) { - defer(function() { - each(newFilteredItems, function( el ) { - var $item = $( el ); - this._transition({ - $item: $item, - opacity: 1, - point: $item.data('point'), - scale: DEFAULT_SCALE - }); - }, this); - - this._whenCollectionDone($(newFilteredItems), TRANSITIONEND, function() { - $(newFilteredItems).css( TRANSITION_DELAY, '0ms' ); - this._movementFinished(); - }); - }, this, this.revealAppendedDelay); -}; - - -/** - * Execute a function when an event has been triggered for every item in a collection. - * @param {jQuery} $collection Collection of elements. - * @param {string} eventName Event to listen for. - * @param {Function} callback Callback to execute when they're done. - * @private - */ -Shuffle.prototype._whenCollectionDone = function( $collection, eventName, callback ) { - var done = 0; - var items = $collection.length; - var self = this; - - function handleEventName( evt ) { - if ( evt.target === evt.currentTarget ) { - $( evt.target ).off( eventName, handleEventName ); - done++; - - // Execute callback if all items have emitted the correct event. - if ( done === items ) { - callback.call( self ); - } - } - } - - // Bind the event to all items. - $collection.on( eventName, handleEventName ); -}; - - -/** - * Execute a callback after jQuery `animate` for a collection has finished. - * @param {Function} callback Callback to execute when they're done. - * @private - */ -Shuffle.prototype._whenAnimationsDone = function( callback ) { - $.when.apply( null, this._animations ).always( $.proxy( function() { - this._animations.length = 0; - callback.call( this ); - }, this )); -}; - - -/** - * Public Methods - */ - -/** - * The magic. This is what makes the plugin 'shuffle' - * @param {string|Function} [category] Category to filter by. Can be a function - * @param {Object} [sortObj] A sort object which can sort the filtered set - */ -Shuffle.prototype.shuffle = function( category, sortObj ) { - if ( !this.enabled || this.isTransitioning ) { - return; - } - - if ( !category ) { - category = ALL_ITEMS; - } - - this._filter( category ); - - // How many filtered elements? - this._updateItemCount(); - - // Shrink each concealed item - this._shrink(); - - // Update transforms on .filtered elements so they will animate to their new positions - this.sort( sortObj ); -}; - - -/** - * Gets the .filtered elements, sorts them, and passes them to layout. - * @param {Object} opts the options object for the sorted plugin - */ -Shuffle.prototype.sort = function( opts ) { - if ( this.enabled && !this.isTransitioning ) { - this._resetCols(); - - var sortOptions = opts || this.lastSort; - var items = this._getFilteredItems().sorted( sortOptions ); - - this._layout( items ); - - this.lastSort = sortOptions; - } -}; - - -/** - * Reposition everything. - * @param {boolean} isOnlyLayout If true, column and gutter widths won't be - * recalculated. - */ -Shuffle.prototype.update = function( isOnlyLayout ) { - if ( this.enabled && !this.isTransitioning ) { - - if ( !isOnlyLayout ) { - // Get updated colCount - this._setColumns(); - } - - // Layout items - this.sort(); - } -}; - - -/** - * Use this instead of `update()` if you don't need the columns and gutters updated - * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations - * could be off. - */ -Shuffle.prototype.layout = function() { - this.update( true ); -}; - - -/** - * New items have been appended to shuffle. Fade them in sequentially - * @param {jQuery} $newItems jQuery collection of new items - * @param {boolean} [addToEnd=false] If true, new items will be added to the end / bottom - * of the items. If not true, items will be mixed in with the current sort order. - * @param {boolean} [isSequential=true] If false, new items won't sequentially fade in - */ -Shuffle.prototype.appended = function( $newItems, addToEnd, isSequential ) { - this._addItems( $newItems, addToEnd === true, isSequential !== false ); -}; - - -/** - * Disables shuffle from updating dimensions and layout on resize - */ -Shuffle.prototype.disable = function() { - this.enabled = false; -}; - - -/** - * Enables shuffle again - * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters - */ -Shuffle.prototype.enable = function( isUpdateLayout ) { - this.enabled = true; - if ( isUpdateLayout !== false ) { - this.update(); - } -}; - - -/** - * Remove 1 or more shuffle items - * @param {jQuery} $collection A jQuery object containing one or more element in shuffle - * @return {Shuffle} The shuffle object - */ -Shuffle.prototype.remove = function( $collection ) { - - // If this isn't a jquery object, exit - if ( !$collection.length || !$collection.jquery ) { - return; - } - - function handleRemoved() { - // Remove the collection in the callback - $collection.remove(); - - // Update things now that elements have been removed. - this.$items = this._getItems(); - this._updateItemCount(); - - this._fire( Shuffle.EventType.REMOVED, [ $collection, this ] ); - - // Let it get garbage collected - $collection = null; - } - - // Hide collection first. - this._toggleFilterClasses( $(), $collection ); - this._shrink( $collection ); - - this.sort(); - - this.$el.one( Shuffle.EventType.LAYOUT + '.' + SHUFFLE, $.proxy( handleRemoved, this ) ); -}; - - -/** - * Destroys shuffle, removes events, styles, and classes - */ -Shuffle.prototype.destroy = function() { - // If there is more than one shuffle instance on the page, - // removing the resize handler from the window would remove them - // all. This is why a unique value is needed. - $window.off('.' + this.unique); - - // Reset container styles - this.$el - .removeClass( SHUFFLE ) - .removeAttr('style') - .removeData( SHUFFLE ); - - // Reset individual item styles - this.$items - .removeAttr('style') - .removeData('point') - .removeData('scale') - .removeClass([ - Shuffle.ClassName.CONCEALED, - Shuffle.ClassName.FILTERED, - Shuffle.ClassName.SHUFFLE_ITEM - ].join(' ')); - - // Null DOM references - this.$items = null; - this.$el = null; - this.sizer = null; - this.element = null; - - // Set a flag so if a debounced resize has been triggered, - // it can first check if it is actually destroyed and not doing anything - this.destroyed = true; -}; - - -// Plugin definition -$.fn.shuffle = function( opts ) { - var args = Array.prototype.slice.call( arguments, 1 ); - return this.each(function() { - var $this = $( this ); - var shuffle = $this.data( SHUFFLE ); - - // If we don't have a stored shuffle, make a new one and save it - if ( !shuffle ) { - shuffle = new Shuffle( this, opts ); - $this.data( SHUFFLE, shuffle ); - } else if ( typeof opts === 'string' && shuffle[ opts ] ) { - shuffle[ opts ].apply( shuffle, args ); - } - }); -}; - - -// http://stackoverflow.com/a/962890/373422 -function randomize( array ) { - var tmp, current; - var top = array.length; - - if ( !top ) { - return array; - } - - while ( --top ) { - current = Math.floor( Math.random() * (top + 1) ); - tmp = array[ current ]; - array[ current ] = array[ top ]; - array[ top ] = tmp; - } - - return array; -} - - -// You can return `undefined` from the `by` function to revert to DOM order -// This plugin does NOT return a jQuery object. It returns a plain array because -// jQuery sorts everything in DOM order. -$.fn.sorted = function(options) { - var opts = $.extend({}, $.fn.sorted.defaults, options); - var arr = this.get(); - var revert = false; - - if ( !arr.length ) { - return []; - } - - if ( opts.randomize ) { - return randomize( arr ); - } - - // Sort the elements by the opts.by function. - // If we don't have opts.by, default to DOM order - if ( $.isFunction( opts.by ) ) { - arr.sort(function(a, b) { - - // Exit early if we already know we want to revert - if ( revert ) { - return 0; - } - - var valA = opts.by($(a)); - var valB = opts.by($(b)); - - // If both values are undefined, use the DOM order - if ( valA === undefined && valB === undefined ) { - revert = true; - return 0; - } - - if ( valA < valB || valA === 'sortFirst' || valB === 'sortLast' ) { - return -1; - } - - if ( valA > valB || valA === 'sortLast' || valB === 'sortFirst' ) { - return 1; - } - - return 0; - }); - } - - // Revert to the original array if necessary - if ( revert ) { - return this.get(); - } - - if ( opts.reverse ) { - arr.reverse(); - } - - return arr; -}; - - -$.fn.sorted.defaults = { - reverse: false, // Use array.reverse() to reverse the results - by: null, // Sorting function - randomize: false // If true, this will skip the sorting and return a randomized order in the array -}; - -return Shuffle; - -}); \ No newline at end of file diff --git a/docs/js/mydoc_scroll.html b/docs/js/mydoc_scroll.html deleted file mode 100644 index 39fa55e992..0000000000 --- a/docs/js/mydoc_scroll.html +++ /dev/null @@ -1,240 +0,0 @@ ---- -title: Scroll layout -type: scroll -keywords: json, scrolling, scrollto, jquery plugin -tags: special_layouts -last_updated: November 30, 2015 -summary: "This page demonstrates how you the integration of a script called ScrollTo, which is used here to link definitions of a JSON code sample to a list of definitions for that particular term. The scenario here is that the JSON blocks are really long, with extensive nesting and subnesting, which makes it difficult for tables below the JSON to adequately explain the term in a usable way." ---- - -{% if site.output == "pdf" %} -{{site.data.alerts.note}} The content on this page doesn't display well on PDF, but I included it anyway so you could see the problems this layout poses if you're including it in PDF. {{site.data.alerts.end}} -{% endif %} - -{% if site.output == "web" %} - - - - - - - - - - -
    -
    - - -
    -
    - - -{{site.data.alerts.note}} This was mostly an experiment to see if there was a better way to document a long JSON code example. I haven't actually used this approach in my own documentation.{{site.data.alerts.end}} - -{% endif %} - diff --git a/docs/js/shuffle.js b/docs/js/shuffle.js new file mode 100644 index 0000000000..37ca4bbf7b --- /dev/null +++ b/docs/js/shuffle.js @@ -0,0 +1,92 @@ +/* + * Adjusted sample from original: https://vestride.github.io/Shuffle/js/demos/homepage.js + */ +(function() { + +'use strict'; + +var Shuffle = window.Shuffle; + +var DocShuffle = function () { + this.element = document.querySelector('#grid'); + + this.shuffle = new Shuffle(this.element, { + itemSelector: 'div[data-groups]', + sizer: this.element.querySelector('.shuffle_sizer'), + }); + + this.addFilterButtons(); + this.addLinkTargetHighlighting(); +}; + +DocShuffle.prototype.addFilterButtons = function () { + var options = document.querySelector('.filter-options'); + + if (!options) { + return; + } + + var filterButtons = Array.from(options.children); + + filterButtons.forEach(function (button) { + button.addEventListener('click', this._handleFilterClick.bind(this), false); + }, this); +}; + +DocShuffle.prototype._handleFilterClick = function (evt) { + var btn = evt.currentTarget; + var isActive = btn.classList.contains('active'); + var btnGroup = btn.getAttribute('data-group'); + + this._removeActiveClassFromChildren(btn.parentNode); + + var filterGroup; + if (isActive) { + btn.classList.remove('active'); + filterGroup = Shuffle.ALL_ITEMS; + } else { + btn.classList.add('active'); + filterGroup = btnGroup; + } + + this.shuffle.filter(filterGroup); +}; + +DocShuffle.prototype._removeActiveClassFromChildren = function (parent) { + var children = parent.children; + for (var i = children.length - 1; i >= 0; i--) { + children[i].classList.remove('active'); + } +}; + +// Adds a pretty animation to links to shuffle panels +// Note: needs jquery-ui +DocShuffle.prototype.addLinkTargetHighlighting = function() { + $("a[href^='#shuffle-panel']").click(function () { + if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '') + && location.hostname === this.hostname) { + var target = $(this.hash); + + target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); + if (target.length) { + $('#topbar-content-offset').animate({ + scrollTop: $('#grid-rule').position().top + }, { + duration: 500, + complete: function () { + target.effect("highlight", {}, 1000); + } + }); + + return false; + } + } + }); +}; + + +document.addEventListener('DOMContentLoaded', function () { + window.docShuffle = new DocShuffle(); +}); + +})(); diff --git a/docs/js/tabstate.js b/docs/js/tabstate.js new file mode 100644 index 0000000000..529dcc5bb3 --- /dev/null +++ b/docs/js/tabstate.js @@ -0,0 +1,43 @@ +// needed for nav tabs on pages. See Formatting > Nav tabs for more details. +// script from http://stackoverflow.com/questions/10523433/how-do-i-keep-the-current-tab-active-with-twitter-bootstrap-after-a-page-reload +(function() { + var registerTabEvent = function() { + $('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) { + var tabId, json, parentId, tabsState; + + tabsState = localStorage.getItem("tabs-state"); + json = JSON.parse(tabsState || "{}"); + parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id"); + tabId = $(e.target).attr('id'); + json[parentId] = tabId; + + return localStorage.setItem("tabs-state", JSON.stringify(json)); + }); + }; + + document.addEventListener('DOMContentLoaded', function () { + var json, tabsState; + tabsState = localStorage.getItem("tabs-state"); + json = JSON.parse(tabsState || "{}"); + + $.each(json, function(containerId, tabId) { + if (containerId && containerId !== "undefined" && tabId && tabId !== "undefined" + && tabId.indexOf('#') !== 0) { + $("#" + tabId).tab('show'); + } + }); + + $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() { + var $this = $(this); + if (!json[$this.attr("id")]) { + return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show"); + } + }); + + // cleanup "undefined" entries + delete json['undefined']; + localStorage.setItem("tabs-state", JSON.stringify(json)); + + registerTabEvent(); + }); +})(); diff --git a/docs/pages/7_0_0_release_notes.md b/docs/pages/7_0_0_release_notes.md index ca506e93fa..ad8e836afd 100644 --- a/docs/pages/7_0_0_release_notes.md +++ b/docs/pages/7_0_0_release_notes.md @@ -69,6 +69,10 @@ The following previously deprecated rules have been finally removed: ### Fixed Issues +* java-bestpractices + * [#2796](https://github.com/pmd/pmd/issue/2796): \[java] UnusedAssignment false positive with call chains + * [#2797](https://github.com/pmd/pmd/issues/2797): \[java] MissingOverride long-standing issues + ### API Changes * [#1648](https://github.com/pmd/pmd/pull/1702): \[apex,vf] Remove CodeClimate dependency - [Robert Sösemann](https://github.com/rsoesemann) diff --git a/docs/pages/next_major_development.md b/docs/pages/next_major_development.md index 0fc5e24559..31dd1316bd 100644 --- a/docs/pages/next_major_development.md +++ b/docs/pages/next_major_development.md @@ -18,6 +18,8 @@ the logo in anywhere without offense. The current tasks are listed here: [Integrate new PMD logo #1931](https://github.com/pmd/pmd/issues/1931) +The new logo is available from the [Logo Project Page](pmd_projectdocs_logo.html). + ### API The API of PMD has been growing over the years and needs to be cleaned up. The goal is, to @@ -244,6 +246,34 @@ the breaking API changes will be performed in 7.0.0. an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0, we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %} +#### 6.29.0 + +No changes. + +#### 6.28.0 + +##### Deprecated API + +###### For removal + +* {% jdoc !!core::RuleViolationComparator %}. Use {% jdoc !!core::RuleViolation#DEFAULT_COMPARATOR %} instead. +* {% jdoc !!core::cpd.AbstractTokenizer %}. Use {% jdoc !!core::cpd.AnyTokenizer %} instead. +* {% jdoc !!fortran::cpd.FortranTokenizer %}. Was replaced by an {% jdoc core::cpd.AnyTokenizer %}. Use {% jdoc !!fortran::cpd.FortranLanguage#getTokenizer() %} anyway. +* {% jdoc !!perl::cpd.PerlTokenizer %}. Was replaced by an {% jdoc core::cpd.AnyTokenizer %}. Use {% jdoc !!perl::cpd.PerlLanguage#getTokenizer() %} anyway. +* {% jdoc !!ruby::cpd.RubyTokenizer %}. Was replaced by an {% jdoc core::cpd.AnyTokenizer %}. Use {% jdoc !!ruby::cpd.RubyLanguage#getTokenizer() %} anyway. +* {% jdoc !!core::lang.rule.RuleReference#getOverriddenLanguage() %} and + {% jdoc !!core::lang.rule.RuleReference#setLanguage(net.sourceforge.pmd.lang.Language) %} +* Antlr4 generated lexers: + * {% jdoc !!cs::lang.cs.antlr4.CSharpLexer %} will be moved to package `net.sourceforge.pmd.lang.cs.ast` with PMD 7. + * {% jdoc !!dart::lang.dart.antlr4.Dart2Lexer %} will be renamed to `DartLexer` and moved to package + `net.sourceforge.pmd.lang.dart.ast` with PMD 7. All other classes in the old package will be removed. + * {% jdoc !!go::lang.go.antlr4.GolangLexer %} will be moved to package + `net.sourceforge.pmd.lang.go.ast` with PMD 7. All other classes in the old package will be removed. + * {% jdoc !!kotlin::lang.kotlin.antlr4.Kotlin %} will be renamed to `KotlinLexer` and moved to package + `net.sourceforge.pmd.lang.kotlin.ast` with PMD 7. + * {% jdoc !!lua::lang.lua.antlr4.LuaLexer %} will be moved to package + `net.sourceforge.pmd.lang.lua.ast` with PMD 7. All other classes in the old package will be removed. + #### 6.27.0 * XML rule definition in rulesets: In PMD 7, the `language` attribute will be required on all `rule` diff --git a/docs/pages/pmd/devdocs/development.md b/docs/pages/pmd/devdocs/development.md index 450a47cda2..f7e47c89fd 100644 --- a/docs/pages/pmd/devdocs/development.md +++ b/docs/pages/pmd/devdocs/development.md @@ -18,7 +18,7 @@ The complete source code can be found on github: ## Continuous Integration -We use [Travis CI](https://travis-ci.org/pmd) as our ci service. The main repo and the eclipse plugin are built for +We use [Travis CI](https://travis-ci.com/pmd) as our ci service. The main repo and the eclipse plugin are built for every push. Each pull request is built as well. The maven snapshot artifacts are deployed at [Sonatypes OSS snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/net/sourceforge/pmd/pmd/). diff --git a/docs/pages/pmd/projectdocs/committers/releasing.md b/docs/pages/pmd/projectdocs/committers/releasing.md index e0cfe8a22f..f64b93b896 100644 --- a/docs/pages/pmd/projectdocs/committers/releasing.md +++ b/docs/pages/pmd/projectdocs/committers/releasing.md @@ -6,7 +6,7 @@ author: Romain Pelisse , Andreas Dangel "1" worked ---that's not the case in 2.0 mode. * @ArgumentCount > '1' → `@ArgumentCount > 1` +* In XPath 1.0, the expression `/Foo` matches the *children* of the root named `Foo`. +In XPath 2.0, that expression matches the root, if it is named `Foo`. Consider the following tree: +```java +Foo +└─ Foo +└─ Foo +``` +Then `/Foo` will match the root in XPath 2, and the other nodes (but not the root) in XPath 1. +See eg [an issue caused by this](https://github.com/pmd/pmd/issues/1919#issuecomment-512865434) in Apex, +with nested classes. + + ## Rule properties **See [Defining rule properties](pmd_userdocs_extending_defining_properties.html#for-xpath-rules)** diff --git a/docs/pages/pmd/userdocs/installation.md b/docs/pages/pmd/userdocs/installation.md index 7339d1b986..049fd97564 100644 --- a/docs/pages/pmd/userdocs/installation.md +++ b/docs/pages/pmd/userdocs/installation.md @@ -71,13 +71,17 @@ Additionally, the following options, are specified most of the time even though
    -
    * *
    TitleTypeExcerpt
    ` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Future-proof rule: in browsers that support :focus-visible, suppress the focus outline\n// on elements that programmatically receive focus but wouldn't normally show a visible\n// focus outline. In general, this would mean that the outline is only applied if the\n// interaction that led to the element receiving programmatic focus was a keyboard interaction,\n// or the browser has somehow determined that the user is primarily a keyboard user and/or\n// wants focus outlines to always be presented.\n//\n// See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible\n// and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover() {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n color: inherit;\n text-decoration: none;\n\n @include hover() {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,\n // making it impossible to interact with the content\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `

    ` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Set the cursor for non-`").addClass(this._triggerClass).html(o?t("").attr({src:o,alt:n,title:n}):n)),e[r?"before":"after"](i.trigger),i.trigger.on("click",function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,o=new Date(2009,11,20),a=this._get(t,"dateFormat");a.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},o.setMonth(e(this._get(t,a.match(/MM/)?"monthNames":"monthNamesShort"))),o.setDate(e(this._get(t,a.match(/DD/)?"dayNames":"dayNamesShort"))+20-o.getDay())),t.input.attr("size",this._formatDate(t,o).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,n,o){var r,h,l,c,u,d=this._dialogInst;return d||(this.uuid+=1,r="dp"+this.uuid,this._dialogInput=t(""),this._dialogInput.on("keydown",this._doKeyDown),t("body").append(this._dialogInput),d=this._dialogInst=this._newInst(this._dialogInput,!1),d.settings={},t.data(this._dialogInput[0],"datepicker",d)),a(d.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(d,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,c=document.documentElement.scrollLeft||document.body.scrollLeft,u=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+c,l/2-150+u]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),d.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],"datepicker",d),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,"datepicker");s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).off("focus",this._showDatepicker).off("keydown",this._doKeyDown).off("keypress",this._doKeyPress).off("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty(),m===n&&(m=null))},_enableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,"datepicker");n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,o.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),o=t.data(e,"datepicker");n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,o.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,i,s){var n,o,r,h,l=this._getInst(e);return 2===arguments.length&&"string"==typeof i?"defaults"===i?t.extend({},t.datepicker._defaults):l?"all"===i?t.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),o=this._getDateDatepicker(e,!0),r=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),a(l.settings,n),null!==r&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,r)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(e):this._enableDatepicker(e)),this._attachments(t(e),l),this._autoSize(l),this._setDate(l,o),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,o=t.datepicker._getInst(e.target),a=!0,r=o.dpDiv.is(".ui-datepicker-rtl");if(o._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),a=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",o.dpDiv),n[0]&&t.datepicker._selectDay(e.target,o.selectedMonth,o.selectedYear,n[0]),i=t.datepicker._get(o,"onSelect"),i?(s=t.datepicker._formatDate(o),i.apply(o.input?o.input[0]:null,[s,o])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),a=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),a=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?1:-1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(o,"stepBigMonths"):-t.datepicker._get(o,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),a=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,r?-1:1,"D"),a=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(o,"stepBigMonths"):+t.datepicker._get(o,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),a=e.ctrlKey||e.metaKey;break;default:a=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):a=!1;a&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var i,s,n=t.datepicker._getInst(e.target);return t.datepicker._get(n,"constrainInput")?(i=t.datepicker._possibleChars(t.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),e.ctrlKey||e.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var s,n,o,r,h,l,c;s=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==s&&(t.datepicker._curInst.dpDiv.stop(!0,!0),s&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),n=t.datepicker._get(s,"beforeShow"),o=n?n.apply(e,[e,s]):{},o!==!1&&(a(s.settings,o),s.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(s),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),h={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,s.dpDiv.empty(),s.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(s),h=t.datepicker._checkOffset(s,h,r),s.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),s.inline||(l=t.datepicker._get(s,"showAnim"),c=t.datepicker._get(s,"duration"),s.dpDiv.css("z-index",i(t(e))+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[l]?s.dpDiv.show(l,t.datepicker._get(s,"showOptions"),c):s.dpDiv[l||"show"](l?c:null),t.datepicker._shouldFocusInput(s)&&s.input.trigger("focus"),t.datepicker._curInst=s)) +}},_updateDatepicker:function(e){this.maxRows=4,m=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var i,s=this._getNumberOfMonths(e),n=s[1],a=17,r=e.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.trigger("focus"),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),o=e.dpDiv.outerHeight(),a=e.input?e.input.outerWidth():0,r=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-a:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+r?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+o>l&&l>o?Math.abs(o+r):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,o,a=this._curInst;!a||e&&a!==t.data(e,"datepicker")||this._datepickerShowing&&(i=this._get(a,"showAnim"),s=this._get(a,"duration"),n=function(){t.datepicker._tidyDialog(a)},t.effects&&(t.effects.effect[i]||t.effects[i])?a.dpDiv.hide(i,t.datepicker._get(a,"showOptions"),s,n):a.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,o=this._get(a,"onClose"),o&&o.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),o=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(o,i+("M"===s?this._get(o,"showCurrentAtPos"):0),s),this._updateDatepicker(o))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),o=this._getInst(n[0]);o["selected"+("M"===s?"Month":"Year")]=o["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(o),this._adjustDate(n)},_selectDay:function(e,i,s,n){var o,a=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(a[0])||(o=this._getInst(a[0]),o.selectedDay=o.currentDay=t("a",n).html(),o.selectedMonth=o.currentMonth=i,o.selectedYear=o.currentYear=s,this._selectDate(e,this._formatDate(o,o.currentDay,o.currentMonth,o.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),o=this._getInst(n[0]);i=null!=i?i:this._formatDate(o),o.input&&o.input.val(i),this._updateAlternate(o),s=this._get(o,"onSelect"),s?s.apply(o.input?o.input[0]:null,[i,o]):o.input&&o.input.trigger("change"),o.inline?this._updateDatepicker(o):(this._hideDatepicker(),this._lastInput=o.input[0],"object"!=typeof o.input[0]&&o.input.trigger("focus"),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,o=this._get(e,"altField");o&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(o).val(n))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(e,i,s){if(null==e||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,o,a,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,c="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),u=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,d=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,g=-1,m=-1,_=-1,v=-1,b=!1,y=function(t){var i=e.length>n+1&&e.charAt(n+1)===t;return i&&n++,i},w=function(t){var e=y(t),s="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n="y"===t?s:1,o=RegExp("^\\d{"+n+","+s+"}"),a=i.substring(h).match(o);if(!a)throw"Missing number at position "+h;return h+=a[0].length,parseInt(a[0],10)},k=function(e,s,n){var o=-1,a=t.map(y(e)?n:s,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(a,function(t,e){var s=e[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(o=e[0],h+=s.length,!1):void 0}),-1!==o)return o+1;throw"Unknown name at position "+h},x=function(){if(i.charAt(h)!==e.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;e.length>n;n++)if(b)"'"!==e.charAt(n)||y("'")?x():b=!1;else switch(e.charAt(n)){case"d":_=w("d");break;case"D":k("D",u,d);break;case"o":v=w("o");break;case"m":m=w("m");break;case"M":m=k("M",p,f);break;case"y":g=w("y");break;case"@":r=new Date(w("@")),g=r.getFullYear(),m=r.getMonth()+1,_=r.getDate();break;case"!":r=new Date((w("!")-this._ticksTo1970)/1e4),g=r.getFullYear(),m=r.getMonth()+1,_=r.getDate();break;case"'":y("'")?x():b=!0;break;default:x()}if(i.length>h&&(a=i.substr(h),!/^\s+/.test(a)))throw"Extra/unparsed characters found in date: "+a;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c>=g?0:-100)),v>-1)for(m=1,_=v;;){if(o=this._getDaysInMonth(g,m-1),o>=_)break;m++,_-=o}if(r=this._daylightSavingAdjust(new Date(g,m-1,_)),r.getFullYear()!==g||r.getMonth()+1!==m||r.getDate()!==_)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,o=(i?i.dayNames:null)||this._defaults.dayNames,a=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,o);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),a,r);break;case"y":u+=h("y")?e.getFullYear():(10>e.getFullYear()%100?"0":"")+e.getFullYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,e){return void 0!==t.settings[e]?t.settings[e]:this._defaults[e]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),o=n,a=this._getFormatConfig(t);try{o=this.parseDate(i,s,a)||n}catch(r){s=e?"":s}t.selectedDay=o.getDate(),t.drawMonth=t.selectedMonth=o.getMonth(),t.drawYear=t.selectedYear=o.getFullYear(),t.currentDay=s?o.getDate():0,t.currentMonth=s?o.getMonth():0,t.currentYear=s?o.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},o=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,o=n.getFullYear(),a=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":a+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a));break;case"y":case"Y":o+=parseInt(l[1],10),r=Math.min(r,t.datepicker._getDaysInMonth(o,a))}l=h.exec(i)}return new Date(o,a,r)},a=null==i||""===i?s:"string"==typeof i?o(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return a=a&&"Invalid Date"==""+a?s:a,a&&(a.setHours(0),a.setMinutes(0),a.setSeconds(0),a.setMilliseconds(0)),this._daylightSavingAdjust(a)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,o=t.selectedYear,a=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=a.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=a.getMonth(),t.drawYear=t.selectedYear=t.currentYear=a.getFullYear(),n===t.selectedMonth&&o===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).on(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,o,a,r,h,l,c,u,d,p,f,g,m,_,v,b,y,w,k,x,C,D,I,T,P,M,S,H,z,O,A,N,W,E,F,L,R=new Date,B=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),j=this._get(t,"showButtonPanel"),q=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),U=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),$=this._get(t,"stepMonths"),X=1!==U[0]||1!==U[1],G=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),Q=this._getMinMaxDate(t,"min"),J=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),J)for(e=this._daylightSavingAdjust(new Date(J.getFullYear(),J.getMonth()-U[0]*U[1]+1,J.getDate())),e=Q&&Q>e?Q:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-$,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?""+i+"":q?"":""+i+"",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+$,1)),this._getFormatConfig(t)):n,o=this._canAdjustMonth(t,1,te,Z)?""+n+"":q?"":""+n+"",a=this._get(t,"currentText"),r=this._get(t,"gotoCurrent")&&t.currentDay?G:B,a=K?this.formatDate(a,r,this._getFormatConfig(t)):a,h=t.inline?"":"",l=j?"
    "+(Y?h:"")+(this._isInRange(t,r)?"":"")+(Y?"":h)+"
    ":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),g=this._get(t,"monthNamesShort"),m=this._get(t,"beforeShowDay"),_=this._get(t,"showOtherMonths"),v=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;U[0]>k;k++){for(x="",this.maxRows=4,C=0;U[1]>C;C++){if(D=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),I=" ui-corner-all",T="",X){if(T+="
    "}for(T+="
    "+(/all|left/.test(I)&&0===k?Y?o:s:"")+(/all|right/.test(I)&&0===k?Y?s:o:"")+this._generateMonthYearHeader(t,Z,te,Q,J,k>0||C>0,f,g)+"
    "+"",P=u?"":"",w=0;7>w;w++)M=(w+c)%7,P+="";for(T+=P+"",S=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,S)),H=(this._getFirstDayOfMonth(te,Z)-c+7)%7,z=Math.ceil((H+S)/7),O=X?this.maxRows>z?this.maxRows:z:z,this.maxRows=O,A=this._daylightSavingAdjust(new Date(te,Z,1-H)),N=0;O>N;N++){for(T+="",W=u?"":"",w=0;7>w;w++)E=m?m.apply(t.input?t.input[0]:null,[A]):[!0,""],F=A.getMonth()!==Z,L=F&&!v||!E[0]||Q&&Q>A||J&&A>J,W+="",A.setDate(A.getDate()+1),A=this._daylightSavingAdjust(A);T+=W+""}Z++,Z>11&&(Z=0,te++),T+="
    "+this._get(t,"weekHeader")+"=5?" class='ui-datepicker-week-end'":"")+">"+""+p[M]+"
    "+this._get(t,"calculateWeek")(A)+""+(F&&!_?" ":L?""+A.getDate()+"":""+A.getDate()+"")+"
    "+(X?"
    "+(U[0]>0&&C===U[1]-1?"
    ":""):""),x+=T}y+=x}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var h,l,c,u,d,p,f,g,m=this._get(t,"changeMonth"),_=this._get(t,"changeYear"),v=this._get(t,"showMonthAfterYear"),b="
    ",y="";if(o||!m)y+=""+a[e]+"";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+=""}if(v||(b+=y+(!o&&m&&_?"":" ")),!t.yearshtml)if(t.yearshtml="",o||!_)b+=""+i+"";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);return isNaN(e)?d:e},f=p(u[0]),g=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,g=n?Math.min(g,n.getFullYear()):g,t.yearshtml+="",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),v&&(b+=(!o&&m&&_?"":" ")+y),b+="
    "},_adjustInstDate:function(t,e,i){var s=t.selectedYear+("Y"===i?e:0),n=t.selectedMonth+("M"===i?e:0),o=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),a=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,o)));t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),o=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&o.setDate(this._getDaysInMonth(o.getFullYear(),o.getMonth())),this._isInRange(t,o)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),o=this._getMinMaxDate(t,"max"),a=null,r=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),a=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(a+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||e.getTime()>=n.getTime())&&(!o||e.getTime()<=o.getTime())&&(!a||e.getFullYear()>=a)&&(!r||r>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).on("mousedown",t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new s,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.12.1",t.datepicker,t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var _=!1;t(document).on("mouseup",function(){_=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!_){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,n="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),_=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,_=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("
    ").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())} +},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),h=t.pageX,l=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,h=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(h=this.originalPageX),"x"===a.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY=0;d--)h=s.snapElements[d].left-s.margins.left,l=h+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,h-g>_||m>l+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(h-_),r=g>=Math.abs(l-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(h-m),r=g>=Math.abs(l-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
    "),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
    "),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),g&&(p-=l),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.dialog",{version:"1.12.1",options:{appendTo:"body",autoOpen:!0,buttons:[],classes:{"ui-dialog":"ui-corner-all","ui-dialog-titlebar":"ui-corner-all"},closeOnEscape:!0,closeText:"Close",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var i=t(this).css(e).offset().top;0>i&&t(this).css("top",e.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),null==this.options.title&&null!=this.originalTitle&&(this.options.title=this.originalTitle),this.options.disabled&&(this.options.disabled=!1),this._createWrapper(),this.element.show().removeAttr("title").appendTo(this.uiDialog),this._addClass("ui-dialog-content","ui-widget-content"),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().css(this.originalCss).detach(),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog +},disable:t.noop,enable:t.noop,close:function(e){var i=this;this._isOpen&&this._trigger("beforeClose",e)!==!1&&(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),this.opener.filter(":focusable").trigger("focus").length||t.ui.safeBlur(t.ui.safeActiveElement(this.document[0])),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+t(this).css("z-index")}).get(),o=Math.max.apply(null,n);return o>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",o+1),s=!0),s&&!i&&this._trigger("focus",e),s},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=t(t.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var t=this._focusedElement;t||(t=this.element.find("[autofocus]")),t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).trigger("focus")},_keepFocus:function(e){function i(){var e=t.ui.safeActiveElement(this.document[0]),i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("
    ").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),void 0;if(e.keyCode===t.ui.keyCode.TAB&&!e.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(this._delay(function(){n.trigger("focus")}),e.preventDefault()):(this._delay(function(){s.trigger("focus")}),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("
    "),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=t("").button({label:t("").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(e,"ui-dialog-title"),this._title(e),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html(" ")},_createButtonPane:function(){this.uiDialogButtonPane=t("
    "),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("
    ").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this._removeClass(this.uiDialog,"ui-dialog-buttons"),void 0):(t.each(i,function(i,s){var n,o;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,o={icon:s.icon,iconPosition:s.iconPosition,showLabel:s.showLabel,icons:s.icons,text:s.text},delete s.click,delete s.icon,delete s.iconPosition,delete s.showLabel,delete s.icons,"boolean"==typeof s.text&&delete s.text,t("",s).button(o).appendTo(e.uiButtonSet).on("click",function(){n.apply(e.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){i._addClass(t(this),"ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,e(n))},drag:function(t,s){i._trigger("drag",t,e(s))},stop:function(n,o){var a=o.offset.left-i.document.scrollLeft(),r=o.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(a>=0?"+":"")+a+" "+"top"+(r>=0?"+":"")+r,of:i.window},i._removeClass(t(this),"ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,e(o))}})},_makeResizable:function(){function e(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}var i=this,s=this.options,n=s.resizable,o=this.uiDialog.css("position"),a="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:a,start:function(s,n){i._addClass(t(this),"ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,e(n))},resize:function(t,s){i._trigger("resize",t,e(s))},stop:function(n,o){var a=i.uiDialog.offset(),r=a.left-i.document.scrollLeft(),h=a.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},i._removeClass(t(this),"ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,e(o))}}).css("position",o)},_trackFocus:function(){this._on(this.widget(),{focusin:function(e){this._makeFocusTarget(),this._focusedElement=t(e.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var e=this._trackingInstances(),i=t.inArray(this,e);-1!==i&&e.splice(i,1)},_trackingInstances:function(){var t=this.document.data("ui-dialog-instances");return t||(t=[],this.document.data("ui-dialog-instances",t)),t},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(e){var i=this,s=!1,n={};t.each(e,function(t,e){i._setOption(t,e),t in i.sizeRelatedOptions&&(s=!0),t in i.resizableRelatedOptions&&(n[t]=e)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,i){var s,n,o=this.uiDialog;"disabled"!==e&&(this._super(e,i),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:t("").text(""+this.options.closeText).html()}),"draggable"===e&&(s=o.is(":data(ui-draggable)"),s&&!i&&o.draggable("destroy"),!s&&i&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(n=o.is(":data(ui-resizable)"),n&&!i&&o.resizable("destroy"),n&&"string"==typeof i&&o.resizable("option","handles",i),n||i===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var e=t(this);return t("
    ").css({position:"absolute",width:e.outerWidth(),height:e.outerHeight()}).appendTo(e.parent()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(e){return t(e.target).closest(".ui-dialog").length?!0:!!t(e.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var e=!0;this._delay(function(){e=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(t){e||this._allowInteraction(t)||(t.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=t("
    ").appendTo(this._appendTo()),this._addClass(this.overlay,null,"ui-widget-overlay ui-front"),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var t=this.document.data("ui-dialog-overlays")-1;t?this.document.data("ui-dialog-overlays",t):(this._off(this.document,"focusin"),this.document.removeData("ui-dialog-overlays")),this.overlay.remove(),this.overlay=null}}}),t.uiBackCompat!==!1&&t.widget("ui.dialog",t.ui.dialog,{options:{dialogClass:""},_createWrapper:function(){this._super(),this.uiDialog.addClass(this.options.dialogClass)},_setOption:function(t,e){"dialogClass"===t&&this.uiDialog.removeClass(this.options.dialogClass).addClass(e),this._superApply(arguments)}}),t.ui.dialog,t.widget("ui.droppable",{version:"1.12.1",widgetEventPrefix:"drop",options:{accept:"*",addClasses:!0,greedy:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],void 0):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this._addClass("ui-droppable")},_addToManager:function(e){t.ui.ddmanager.droppables[e]=t.ui.ddmanager.droppables[e]||[],t.ui.ddmanager.droppables[e].push(this)},_splice:function(t){for(var e=0;t.length>e;e++)t[e]===this&&t.splice(e,1)},_destroy:function(){var e=t.ui.ddmanager.droppables[this.options.scope];this._splice(e)},_setOption:function(e,i){if("accept"===e)this.accept=t.isFunction(i)?i:function(t){return t.is(i)};else if("scope"===e){var s=t.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(e,i)},_activate:function(e){var i=t.ui.ddmanager.current;this._addActiveClass(),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this._removeActiveClass(),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._addHoverClass(),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._removeHoverClass(),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=t(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&v(s,t.extend(i,{offset:i.element.offset()}),i.options.tolerance,e)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this._removeActiveClass(),this._removeHoverClass(),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}},_addHoverClass:function(){this._addClass("ui-droppable-hover")},_removeHoverClass:function(){this._removeClass("ui-droppable-hover")},_addActiveClass:function(){this._addClass("ui-droppable-active")},_removeActiveClass:function(){this._removeClass("ui-droppable-active")}});var v=t.ui.intersect=function(){function t(t,e,i){return t>=e&&e+i>t}return function(e,i,s,n){if(!i.offset)return!1;var o=(e.positionAbs||e.position.absolute).left+e.margins.left,a=(e.positionAbs||e.position.absolute).top+e.margins.top,r=o+e.helperProportions.width,h=a+e.helperProportions.height,l=i.offset.left,c=i.offset.top,u=l+i.proportions().width,d=c+i.proportions().height;switch(s){case"fit":return o>=l&&u>=r&&a>=c&&d>=h;case"intersect":return o+e.helperProportions.width/2>l&&u>r-e.helperProportions.width/2&&a+e.helperProportions.height/2>c&&d>h-e.helperProportions.height/2;case"pointer":return t(n.pageY,c,i.proportions().height)&&t(n.pageX,l,i.proportions().width);case"touch":return(a>=c&&d>=a||h>=c&&d>=h||c>a&&h>d)&&(o>=l&&u>=o||r>=l&&u>=r||l>o&&r>u);default:return!1}}}();t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,o=t.ui.ddmanager.droppables[e.options.scope]||[],a=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;o.length>s;s++)if(!(o[s].options.disabled||e&&!o[s].accept.call(o[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===o[s].element[0]){o[s].proportions().height=0;continue t}o[s].visible="none"!==o[s].element.css("display"),o[s].visible&&("mousedown"===a&&o[s]._activate.call(o[s],i),o[s].offset=o[s].element.offset(),o[s].proportions({width:o[s].element[0].offsetWidth,height:o[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&v(e,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").on("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,o,a=v(e,this,this.options.tolerance,i),r=!a&&this.isover?"isout":a&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,o=this.element.parents(":data(ui-droppable)").filter(function(){return t(this).droppable("instance").options.scope===n}),o.length&&(s=t(o[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").off("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}},t.uiBackCompat!==!1&&t.widget("ui.droppable",t.ui.droppable,{options:{hoverClass:!1,activeClass:!1},_addActiveClass:function(){this._super(),this.options.activeClass&&this.element.addClass(this.options.activeClass)},_removeActiveClass:function(){this._super(),this.options.activeClass&&this.element.removeClass(this.options.activeClass)},_addHoverClass:function(){this._super(),this.options.hoverClass&&this.element.addClass(this.options.hoverClass)},_removeHoverClass:function(){this._super(),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass)}}),t.ui.droppable,t.widget("ui.progressbar",{version:"1.12.1",options:{classes:{"ui-progressbar":"ui-corner-all","ui-progressbar-value":"ui-corner-left","ui-progressbar-complete":"ui-corner-right"},max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.attr({role:"progressbar","aria-valuemin":this.min}),this._addClass("ui-progressbar","ui-widget ui-widget-content"),this.valueDiv=t("
    ").appendTo(this.element),this._addClass(this.valueDiv,"ui-progressbar-value","ui-widget-header"),this._refreshValue()},_destroy:function(){this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"),this.valueDiv.remove()},value:function(t){return void 0===t?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),void 0)},_constrainedValue:function(t){return void 0===t&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).width(i.toFixed(0)+"%"),this._toggleClass(this.valueDiv,"ui-progressbar-complete",null,e===this.options.max)._toggleClass("ui-progressbar-indeterminate",null,this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("
    ").appendTo(this.valueDiv),this._addClass(this.overlayDiv,"ui-progressbar-overlay"))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}}),t.widget("ui.selectable",t.ui.mouse,{version:"1.12.1",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e.elementPos=t(e.element[0]).offset(),e.selectees=t(e.options.filter,e.element[0]),e._addClass(e.selectees,"ui-selectee"),e.selectees.each(function(){var i=t(this),s=i.offset(),n={left:s.left-e.elementPos.left,top:s.top-e.elementPos.top};t.data(this,"selectable-item",{element:this,$element:i,left:n.left,top:n.top,right:n.left+i.outerWidth(),bottom:n.top+i.outerHeight(),startselected:!1,selected:i.hasClass("ui-selected"),selecting:i.hasClass("ui-selecting"),unselecting:i.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=t("
    "),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.elementPos=t(this.element[0]).offset(),this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(i._removeClass(s.$element,"ui-selected"),s.selected=!1,i._addClass(s.$element,"ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),i._removeClass(n.$element,s?"ui-unselecting":"ui-selected")._addClass(n.$element,s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,o=this.opos[0],a=this.opos[1],r=e.pageX,h=e.pageY;return o>r&&(i=r,r=o,o=i),a>h&&(i=h,h=a,a=i),this.helper.css({left:o,top:a,width:r-o,height:h-a}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),l=!1,c={};i&&i.element!==s.element[0]&&(c.left=i.left+s.elementPos.left,c.right=i.right+s.elementPos.left,c.top=i.top+s.elementPos.top,c.bottom=i.bottom+s.elementPos.top,"touch"===n.tolerance?l=!(c.left>r||o>c.right||c.top>h||a>c.bottom):"fit"===n.tolerance&&(l=c.left>o&&r>c.right&&c.top>a&&h>c.bottom),l?(i.selected&&(s._removeClass(i.$element,"ui-selected"),i.selected=!1),i.unselecting&&(s._removeClass(i.$element,"ui-unselecting"),i.unselecting=!1),i.selecting||(s._addClass(i.$element,"ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,s._addClass(i.$element,"ui-selected"),i.selected=!0):(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,i.startselected&&(s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(s._removeClass(i.$element,"ui-selected"),i.selected=!1,s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-selecting")._addClass(s.$element,"ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}}),t.widget("ui.selectmenu",[t.ui.formResetMixin,{version:"1.12.1",defaultElement:"
     
    + * + * @deprecated This is part of the internals of the {@link RuleSetParser}. */ +@Deprecated +@InternalApi public class RuleSetReferenceId { private final boolean external; private final String ruleSetFileName; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java index ff790275f6..563540e6a7 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/RulesetsFactoryUtils.java @@ -9,11 +9,12 @@ import java.util.logging.Level; import java.util.logging.Logger; import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.benchmark.TimeTracker; -import net.sourceforge.pmd.benchmark.TimedOperation; -import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.util.ResourceLoader; +/** + * @deprecated Use a {@link RuleSetParser} instead + */ +@Deprecated public final class RulesetsFactoryUtils { private static final Logger LOG = Logger.getLogger(RulesetsFactoryUtils.class.getName()); @@ -37,10 +38,10 @@ public final class RulesetsFactoryUtils { */ @InternalApi @Deprecated - public static List getRuleSets(String rulesets, RuleSetFactory factory) { + public static List getRuleSets(String rulesets, RuleSetParser factory) { List ruleSets; try { - ruleSets = factory.createRuleSets(rulesets); + ruleSets = factory.parseFromResources(rulesets.split(",")); printRuleNamesInDebug(ruleSets); if (ruleSets.stream().mapToInt(RuleSet::size).sum() == 0) { String msg = "No rules found. Maybe you misspelled a rule name? (" + rulesets + ')'; @@ -55,29 +56,7 @@ public final class RulesetsFactoryUtils { } /** - * See {@link #getRuleSets(String, RuleSetFactory)}. In addition, the - * loading of the rules is benchmarked. - * - * @param rulesets - * the string with the rulesets to load - * @param factory - * the ruleset factory - * @return the rulesets - * @throws IllegalArgumentException - * if rulesets is empty (means, no rules have been found) or if - * a ruleset couldn't be found. - * @deprecated Is internal API - */ - @InternalApi - @Deprecated - public static List getRuleSetsWithBenchmark(String rulesets, RuleSetFactory factory) { - try (TimedOperation to = TimeTracker.startOperation(TimedOperationCategory.LOAD_RULES)) { - return getRuleSets(rulesets, factory); - } - } - - /** - * @deprecated Use {@link #createFactory(PMDConfiguration)} or {@link #createFactory(PMDConfiguration, ClassLoader)} + * @deprecated Use a {@link RuleSetParser} */ @InternalApi @Deprecated @@ -97,7 +76,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration, ClassLoader) + * + * @deprecated Use {@link RuleSetParser#fromPmdConfig(PMDConfiguration)} */ + @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration) { return createFactory(configuration, RulesetsFactoryUtils.class.getClassLoader()); } @@ -108,7 +90,7 @@ public final class RulesetsFactoryUtils { * * @return A ruleset factory * - * @see #createFactory(PMDConfiguration, ClassLoader) + * @see RuleSetParser */ public static RuleSetFactory defaultFactory() { return new RuleSetFactory(); @@ -125,7 +107,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetParser} */ + @Deprecated public static RuleSetFactory createFactory(final PMDConfiguration configuration, ClassLoader classLoader) { return createFactory(classLoader, configuration.getMinimumPriority(), @@ -146,7 +131,10 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetParser} */ + @Deprecated public static RuleSetFactory createFactory(ClassLoader classLoader, RulePriority minimumPriority, boolean warnDeprecated, @@ -167,14 +155,44 @@ public final class RulesetsFactoryUtils { * @return A ruleset factory * * @see #createFactory(PMDConfiguration) + * + * @deprecated Use a {@link RuleSetParser} */ + @Deprecated public static RuleSetFactory createFactory(RulePriority minimumPriority, boolean warnDeprecated, boolean enableCompatibility) { - return new RuleSetFactory(new ResourceLoader(), minimumPriority, warnDeprecated, enableCompatibility); } + /** + * Returns a ruleset factory which uses the classloader for PMD + * classes to resolve resource references. + * + * @param minimumPriority Minimum priority for rules to be included + * @param warnDeprecated If true, print warnings when deprecated rules are included + * @param enableCompatibility If true, rule references to moved rules are mapped to their + * new location if they are known + * @param includeDeprecatedRuleReferences If true, deprecated rule references are retained. Usually, these + * references are ignored, since they indicate renamed/moved rules, and the referenced + * rule is often included in the same ruleset. Enabling this might result in + * duplicated rules. + * + * @return A ruleset factory + * + * @see #createFactory(PMDConfiguration) + * @deprecated Use a {@link RuleSetParser} + */ + @Deprecated + public static RuleSetFactory createFactory(RulePriority minimumPriority, + boolean warnDeprecated, + boolean enableCompatibility, + boolean includeDeprecatedRuleReferences) { + + return new RuleSetFactory(new ResourceLoader(), minimumPriority, warnDeprecated, enableCompatibility, + includeDeprecatedRuleReferences); + } + /** * If in debug modus, print the names of the rules. * @@ -183,8 +201,8 @@ public final class RulesetsFactoryUtils { private static void printRuleNamesInDebug(List rulesets) { if (LOG.isLoggable(Level.FINER)) { for (RuleSet rset : rulesets) { - for (Rule rule : rset.getRules()) { - LOG.finer("Loaded rule " + rule.getName()); + for (Rule r : rset.getRules()) { + LOG.finer("Loaded rule " + r.getName()); } } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java index 2ef0afd459..3ed459d55c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/Formatter.java @@ -23,11 +23,15 @@ import java.util.Properties; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; import org.apache.tools.ant.types.Parameter; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.renderers.Renderer; import net.sourceforge.pmd.renderers.RendererFactory; +import net.sourceforge.pmd.reporting.FileAnalysisListener; +import net.sourceforge.pmd.reporting.GlobalAnalysisListener; +import net.sourceforge.pmd.util.document.TextFile; public class Formatter { @@ -182,8 +186,7 @@ public class Formatter { boolean isOnError = true; try { output = Files.newOutputStream(file.toPath()); - writer = new OutputStreamWriter(output, charset); - writer = new BufferedWriter(writer); + writer = new BufferedWriter(new OutputStreamWriter(output, charset)); isOnError = false; } finally { if (isOnError) { @@ -226,4 +229,26 @@ public class Formatter { } return null; } + + public GlobalAnalysisListener newListener(Project project) throws IOException { + start(project.getBaseDir().toString()); + Renderer renderer = getRenderer(); + + return new GlobalAnalysisListener() { + final GlobalAnalysisListener listener = renderer.newListener(); + + @Override + public FileAnalysisListener startFileAnalysis(TextFile file) { + return listener.startFileAnalysis(file); + } + + @Override + public void close() throws Exception { + listener.close(); + if (!toConsole) { + writer.close(); + } + } + }; + } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java index e7903be003..31bb931bed 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/ant/internal/PMDTaskImpl.java @@ -5,12 +5,9 @@ package net.sourceforge.pmd.ant.internal; import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.StringJoiner; import org.apache.commons.lang3.StringUtils; import org.apache.tools.ant.AntClassLoader; @@ -23,7 +20,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; -import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; @@ -36,9 +32,9 @@ import net.sourceforge.pmd.ant.SourceLanguage; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; -import net.sourceforge.pmd.renderers.AbstractRenderer; -import net.sourceforge.pmd.renderers.Renderer; +import net.sourceforge.pmd.reporting.FileAnalysisListener; import net.sourceforge.pmd.reporting.GlobalAnalysisListener; +import net.sourceforge.pmd.reporting.GlobalAnalysisListener.ViolationCounterListener; import net.sourceforge.pmd.util.ClasspathClassLoader; import net.sourceforge.pmd.util.FileUtil; import net.sourceforge.pmd.util.IOUtil; @@ -54,7 +50,6 @@ public class PMDTaskImpl { private final List formatters = new ArrayList<>(); private final List filesets = new ArrayList<>(); private final PMDConfiguration configuration = new PMDConfiguration(); - private boolean failOnError; private boolean failOnRuleViolation; private int maxRuleViolations = 0; private String failuresPropertyName; @@ -65,7 +60,6 @@ public class PMDTaskImpl { if (task.getSuppressMarker() != null) { configuration.setSuppressMarker(task.getSuppressMarker()); } - this.failOnError = task.isFailOnError(); this.failOnRuleViolation = task.isFailOnRuleViolation(); this.maxRuleViolations = task.getMaxRuleViolations(); if (this.maxRuleViolations > 0) { @@ -126,57 +120,38 @@ public class PMDTaskImpl { project.log("Setting suppress marker to be " + configuration.getSuppressMarker(), Project.MSG_VERBOSE); } - // Start the Formatters - for (Formatter formatter : formatters) { - project.log("Sending a report to " + formatter, Project.MSG_VERBOSE); - formatter.start(project.getBaseDir().toString()); - } - // log("Setting Language Version " + languageVersion.getShortName(), - // Project.MSG_VERBOSE); - - // TODO Do we really need all this in a loop over each FileSet? Seems - // like a lot of redundancy - Report errorReport = new Report(); - final AtomicInteger reportSize = new AtomicInteger(); + @SuppressWarnings("PMD.CloseResource") + ViolationCounterListener reportSizeListener = new ViolationCounterListener(); + final List files = new ArrayList<>(); + final List reportShortNamesPaths = new ArrayList<>(); + StringJoiner fullInputPath = new StringJoiner(","); for (FileSet fs : filesets) { - List files = new LinkedList<>(); DirectoryScanner ds = fs.getDirectoryScanner(project); java.nio.file.Path baseDir = ds.getBasedir().toPath(); - configuration.setInputPaths(baseDir.toString()); for (String srcFile : ds.getIncludedFiles()) { java.nio.file.Path file = baseDir.resolve(srcFile); files.add(FileUtil.createNioTextFile(configuration, file, null)); } - Renderer logRenderer = makeRenderer(reportSize); - List renderers; - try { - renderers = new ArrayList<>(formatters.size() + 1); - renderers.add(logRenderer.newListener()); - for (Formatter formatter : formatters) { - renderers.add(formatter.getRenderer().newListener()); - } - } catch (IOException e) { - handleError(errorReport, e); - return; - } - - try { - PMD.processTextFiles(configuration, rules, files, GlobalAnalysisListener.tee(renderers)); - } catch (Exception pmde) { - handleError(errorReport, pmde); + final String commonInputPath = ds.getBasedir().getPath(); + fullInputPath.add(commonInputPath); + if (configuration.isReportShortNames()) { + reportShortNamesPaths.add(commonInputPath); } } + configuration.setInputPaths(fullInputPath.toString()); - int problemCount = reportSize.get(); + try (GlobalAnalysisListener listener = getListener(reportSizeListener)) { + PMD.processTextFiles(configuration, rules, files, listener); + } catch (Exception e) { + throw new BuildException("Exception while closing data sources", e); + } + + int problemCount = reportSizeListener.getResult(); project.log(problemCount + " problems found", Project.MSG_VERBOSE); - for (Formatter formatter : formatters) { - formatter.end(errorReport); - } - if (failuresPropertyName != null && problemCount > 0) { project.setProperty(failuresPropertyName, String.valueOf(problemCount)); project.log("Setting property " + failuresPropertyName + " to " + problemCount, Project.MSG_VERBOSE); @@ -187,36 +162,40 @@ public class PMDTaskImpl { } } - @NonNull - private AbstractRenderer makeRenderer(AtomicInteger reportSize) { - return new AbstractRenderer("log", "Logging renderer") { + private @NonNull GlobalAnalysisListener getListener(ViolationCounterListener reportSizeListener) { + List renderers = new ArrayList<>(formatters.size() + 1); + try { + renderers.add(makeLogListener()); + renderers.add(reportSizeListener); + for (Formatter formatter : formatters) { + project.log("Sending a report to " + formatter, Project.MSG_VERBOSE); + renderers.add(formatter.newListener(project)); + } + } catch (IOException e) { + // close those opened so far + Exception e2 = IOUtil.closeAll(renderers); + if (e2 != null) { + e.addSuppressed(e2); + } + throw new BuildException("Exception while initializing renderers", e); + } + + return GlobalAnalysisListener.tee(renderers); + } + + private GlobalAnalysisListener makeLogListener() { + return new GlobalAnalysisListener() { + @Override - public void start() { - // Nothing to do + public FileAnalysisListener startFileAnalysis(TextFile dataSource) { + project.log("Processing file " + dataSource.getPathId(), Project.MSG_VERBOSE); + return FileAnalysisListener.noop(); } @Override - public void startFileAnalysis(TextFile dataSource) { - project.log("Processing file " + dataSource.getDisplayName(), Project.MSG_VERBOSE); + public void close() { + // nothing to do } - - @Override - public void renderFileReport(Report r) { - int size = r.getViolations().size(); - if (size > 0) { - reportSize.addAndGet(size); - } - } - - @Override - public void end() { - // Nothing to do - } - - @Override - public String defaultFileExtension() { - return null; - } // not relevant }; } @@ -241,32 +220,6 @@ public class PMDTaskImpl { project, classpath, parentFirst)); } - private void handleError(Report errorReport, Throwable pmde) { - - pmde.printStackTrace(); - project.log(pmde.toString(), Project.MSG_VERBOSE); - - Throwable cause = pmde.getCause(); - - if (cause != null) { - try (StringWriter strWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(strWriter)) { - cause.printStackTrace(printWriter); - project.log(strWriter.toString(), Project.MSG_VERBOSE); - } catch (IOException e) { - project.log("Error while closing stream", e, Project.MSG_ERR); - } - if (StringUtils.isNotBlank(cause.getMessage())) { - project.log(cause.getMessage(), Project.MSG_VERBOSE); - } - } - - if (failOnError) { - throw new BuildException(pmde); - } - errorReport.addError(new Report.ProcessingError(pmde, "(unknown file)")); - } - private void setupClassLoader() { try { if (auxClasspath != null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java index f1282ffdaa..e717973250 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDCommandLineInterface.java @@ -9,6 +9,7 @@ import java.util.stream.Collectors; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDVersion; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -21,7 +22,10 @@ import com.beust.jcommander.ParameterException; /** * @author Romain Pelisse <belaran@gmail.com> * + * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#main(String[])} */ +@Deprecated +@InternalApi public final class PMDCommandLineInterface { public static final String PROG_NAME = "pmd"; diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java index 3877315616..0f37b74d06 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/cli/PMDParameters.java @@ -11,8 +11,10 @@ import java.util.Properties; import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PMDConfiguration; import net.sourceforge.pmd.RulePriority; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; @@ -23,6 +25,11 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.validators.PositiveInteger; +/** + * @deprecated Internal API. Use {@link PMD#run(String[])} or {@link PMD#main(String[])} + */ +@Deprecated +@InternalApi public class PMDParameters { @Parameter(names = { "-rulesets", "-R" }, description = "Comma separated list of ruleset names to use.", diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/Parser.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/Parser.java index 53ea2ad0d4..f5cab2a6aa 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/Parser.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/Parser.java @@ -19,8 +19,6 @@ import net.sourceforge.pmd.util.document.TextDocument; * be stateless (which makes them trivially threadsafe). * * TODO - * - Ideally ParserOptions would be an argument to ::parse - * - ::parse would also take some more parameters, eg an error collector * - The reader + filename would be a TextDocument * * @author Pieter_Van_Raemdonck - Application Engineers NV/SA - www.ae.be diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ParserOptions.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ParserOptions.java index 8e04f9e2bd..2b4ab03d6c 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ParserOptions.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ParserOptions.java @@ -17,14 +17,13 @@ import net.sourceforge.pmd.PMD; * {@link Object#hashCode()}. */ public class ParserOptions { - - private @NonNull String suppressMarker; + private String suppressMarker = PMD.SUPPRESS_MARKER; public final @NonNull String getSuppressMarker() { return suppressMarker; } - public final void setSuppressMarker(String suppressMarker) { + public final void setSuppressMarker(@NonNull String suppressMarker) { Objects.requireNonNull(suppressMarker); this.suppressMarker = suppressMarker; } @@ -46,11 +45,11 @@ public class ParserOptions { return false; } final ParserOptions that = (ParserOptions) obj; - return this.suppressMarker.equals(that.suppressMarker); + return this.getSuppressMarker().equals(that.getSuppressMarker()); } @Override public int hashCode() { - return suppressMarker != null ? suppressMarker.hashCode() : 0; + return getSuppressMarker().hashCode(); } } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/GenericToken.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/GenericToken.java index 23063a584c..f8edf58f7a 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/GenericToken.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/GenericToken.java @@ -113,4 +113,20 @@ public interface GenericToken> extends Comparable, return IteratorUtil.generate(from, t -> t == to ? null : t.getNext()); } + + /** + * Returns an iterable that enumerates all special tokens belonging + * to the given token. + * + * @param from Token from which to start, note that the returned iterable + * does not contain that token + * + * @return An iterator, possibly empty, not containing the parameter + * + * @throws NullPointerException If the parameter s null + */ + static > Iterable previousSpecials(T from) { + return () -> IteratorUtil.generate(from.getPreviousComment(), GenericToken::getPreviousComment); + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java index de9a1fc26e..393a892818 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/Node.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.ast; import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -17,7 +18,6 @@ import net.sourceforge.pmd.lang.ast.NodeStream.DescendantNodeStream; import net.sourceforge.pmd.lang.ast.internal.StreamImpl; import net.sourceforge.pmd.lang.rule.xpath.Attribute; import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; -import net.sourceforge.pmd.lang.rule.xpath.NoAttribute; import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.lang.rule.xpath.impl.AttributeAxisIterator; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; @@ -54,6 +54,12 @@ import net.sourceforge.pmd.util.document.TextRegion; */ public interface Node extends Reportable { + Comparator COORDS_COMPARATOR = + Comparator.comparingInt(Node::getBeginLine) + .thenComparingInt(Node::getBeginColumn) + .thenComparingInt(Node::getEndLine) + .thenComparingInt(Node::getEndColumn); + /** * Returns a string token, usually filled-in by the parser, which describes some textual characteristic of this * node. This is usually an identifier, but you should check that using the Designer. On most nodes though, this @@ -73,6 +79,20 @@ public interface Node extends Reportable { return Objects.equals(getImage(), image); } + /** + * Compare the coordinates of this node with the other one as if + * with {@link #COORDS_COMPARATOR}. The result is useless + * if both nodes are not from the same tree. + * + * @param other Other node + * + * @return A positive integer if this node comes AFTER the other, + * 0 if they have the same position, a negative integer if this + * node comes BEFORE the other + */ + default int compareLocation(Node other) { + return COORDS_COMPARATOR.compare(this, other); + } /** * {@inheritDoc} @@ -86,21 +106,6 @@ public interface Node extends Reportable { FileLocation getReportLocation(); - /** - * Compare the coordinates of this node with the other one as if - * with {@link FileLocation#COORDS_COMPARATOR}. The result is useless - * if both nodes are not from the same tree. - * - * @param node Other node - * - * @return A positive integer if this node comes AFTER the other, - * 0 if they have the same position, a negative integer if this - * node comes BEFORE the other - */ - default int compareLocation(Node node) { - return FileLocation.COORDS_COMPARATOR.compare(getReportLocation(), node.getReportLocation()); - } - // Those are kept here because they're handled specially as XPath // attributes, for now @@ -357,16 +362,6 @@ public interface Node extends Reportable { } - /** - * @deprecated This is simply a placeholder until we have TextDocuments - */ - @Deprecated - @NoAttribute - default String getSourceCodeFile() { - return getTextDocument().getDisplayName(); - } - - /** * Gets the name of the node that is used to match it with XPath queries. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SemanticErrorReporter.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SemanticErrorReporter.java index c822044a33..608b3736e3 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SemanticErrorReporter.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/SemanticErrorReporter.java @@ -5,6 +5,8 @@ package net.sourceforge.pmd.lang.ast; import java.text.MessageFormat; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Reports errors that occur after parsing. This may be used to implement @@ -12,7 +14,6 @@ import java.text.MessageFormat; */ public interface SemanticErrorReporter { // TODO use resource bundle keys instead of string messages. - // TODO do a real implementation, not just a noop /** @@ -23,7 +24,7 @@ public interface SemanticErrorReporter { * @param message Message (rendered using a {@link MessageFormat}) * @param formatArgs Format arguments */ - void warn(Node location, String message, Object... formatArgs); + void warning(Node location, String message, Object... formatArgs); /** @@ -48,7 +49,7 @@ public interface SemanticErrorReporter { private boolean hasError = false; @Override - public void warn(Node location, String message, Object... formatArgs) { + public void warning(Node location, String message, Object... formatArgs) { // noop } @@ -66,4 +67,41 @@ public interface SemanticErrorReporter { } + static SemanticErrorReporter reportToLogger(Logger logger) { + return new SemanticErrorReporter() { + private boolean hasError = false; + + private String locPrefix(Node loc) { + return "[" + loc.getBeginLine() + "," + loc.getBeginColumn() + "] "; + } + + private String makeMessage(Node location, String message, Object[] args) { + return locPrefix(location) + MessageFormat.format(message, args); + } + + private String logMessage(Level level, Node location, String message, Object[] args) { + String fullMessage = makeMessage(location, message, args); + logger.log(level, fullMessage); + return fullMessage; + } + + @Override + public void warning(Node location, String message, Object... args) { + logMessage(Level.WARNING, location, message, args); + } + + @Override + public SemanticException error(Node location, String message, Object... args) { + hasError = true; + String fullMessage = logMessage(Level.SEVERE, location, message, args); + return new SemanticException(fullMessage); + } + + @Override + public boolean hasError() { + return hasError; + } + }; + } + } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/AbstractJjtreeNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/AbstractJjtreeNode.java index 5d8e7d9873..621e574dc1 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/AbstractJjtreeNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/AbstractJjtreeNode.java @@ -70,6 +70,14 @@ public abstract class AbstractJjtreeNode, N e return getTextDocument().toLocation(getTextRegion()); } + @Override + public final int compareLocation(Node other) { + if (other instanceof JjtreeNode) { + return getTextRegion().compareTo(((JjtreeNode) other).getTextRegion()); + } + return super.compareLocation(other); + } + /** * This method is called after the node has been made the current node. It * indicates that child nodes can now be added to it. @@ -90,13 +98,6 @@ public abstract class AbstractJjtreeNode, N e super.addChild(child, index); } - @Override - public int compareLocation(Node node) { - if (node instanceof JjtreeNode) { - return getTextRegion().compareTo(((JjtreeNode) node).getTextRegion()); - } - return JjtreeNode.super.compareLocation(node); - } @Override protected void insertChild(B child, int index) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/JavaccToken.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/JavaccToken.java index 2983cf1109..39f6ea5ca5 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/JavaccToken.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/javacc/JavaccToken.java @@ -45,7 +45,7 @@ public class JavaccToken implements GenericToken { */ public final int kind; - protected final JavaccTokenDocument document; + private final JavaccTokenDocument document; private final CharSequence image; private final int startOffset; private final int endOffset; @@ -75,19 +75,6 @@ public class JavaccToken implements GenericToken { public JavaccToken specialToken; - /** - * @deprecated This is used by a few deprecated tests about comments, - * will be removed when they're updated. - */ - @Deprecated - public JavaccToken(String image) { - this.kind = IMPLICIT_TOKEN; - this.image = image; - this.startOffset = 0; - this.endOffset = 0; - this.document = null; - } - /** * Builds a new token of the specified kind. * @@ -115,7 +102,7 @@ public class JavaccToken implements GenericToken { /** * Returns the document owning this token. */ - public JavaccTokenDocument getDocument() { + public final JavaccTokenDocument getDocument() { return document; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ParametricRuleViolation.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ParametricRuleViolation.java index 6c25dc2040..dddb1ca9c8 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ParametricRuleViolation.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/ParametricRuleViolation.java @@ -6,6 +6,7 @@ package net.sourceforge.pmd.lang.rule; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleViolation; +import net.sourceforge.pmd.internal.util.AssertionUtil; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -27,26 +28,19 @@ public class ParametricRuleViolation implements RuleViolation { protected String methodName = ""; protected String variableName = ""; - // FUTURE Fix to understand when a violation _must_ have a Node, and when it - // must not (to prevent erroneous Rules silently logging w/o a Node). Modify - // RuleViolationFactory to support identifying without a Node, and update - // Rule base classes too. - // TODO we never need a node. We just have to have a Reportable instance - public ParametricRuleViolation(Rule theRule, String filename, T node, String message) { - rule = theRule; - description = message; - this.filename = filename == null ? "" : filename; - - if (node != null) { - beginLine = node.getBeginLine(); - beginColumn = node.getBeginColumn(); - endLine = node.getEndLine(); - endColumn = node.getEndColumn(); - } + public ParametricRuleViolation(Rule theRule, T node, String message) { + this.rule = AssertionUtil.requireParamNotNull("rule", theRule); + this.description = AssertionUtil.requireParamNotNull("message", message); + this.filename = node.getTextDocument().getDisplayName(); + beginLine = node.getBeginLine(); + beginColumn = node.getBeginColumn(); + endLine = node.getEndLine(); + endColumn = node.getEndColumn(); } protected String expandVariables(String message) { + // TODO move that to RuleContext with the rest of the formatting logic if (!message.contains("${")) { return message; @@ -138,6 +132,7 @@ public class ParametricRuleViolation implements RuleViolation { } public void setLines(int theBeginLine, int theEndLine) { + assert theBeginLine > 0 && theEndLine > 0 && theBeginLine <= theEndLine : "Line numbers are 1-based"; beginLine = theBeginLine; endLine = theEndLine; } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleViolationFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleViolationFactory.java index 7496919998..a045cf0ed0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleViolationFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/RuleViolationFactory.java @@ -21,7 +21,7 @@ public interface RuleViolationFactory { // todo move to package reporting - RuleViolation createViolation(Rule rule, @NonNull Node location, String filename, String formattedMessage); + RuleViolation createViolation(Rule rule, @NonNull Node location, String formattedMessage); SuppressedViolation suppressOrNull(Node location, RuleViolation violation); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/impl/DefaultRuleViolationFactory.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/impl/DefaultRuleViolationFactory.java index 17e3ed9d9e..8d0b87fc4f 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/impl/DefaultRuleViolationFactory.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/impl/DefaultRuleViolationFactory.java @@ -33,12 +33,12 @@ public class DefaultRuleViolationFactory implements RuleViolationFactory { private Set allSuppressors; @Override - public RuleViolation createViolation(Rule rule, @NonNull Node location, String filename, String formattedMessage) { - return new ParametricRuleViolation<>(rule, filename, location, formattedMessage); + public RuleViolation createViolation(Rule rule, @NonNull Node location, @NonNull String formattedMessage) { + return new ParametricRuleViolation<>(rule, location, formattedMessage); } @Override - public final SuppressedViolation suppressOrNull(Node location, RuleViolation violation) { + public SuppressedViolation suppressOrNull(Node location, RuleViolation violation) { for (ViolationSuppressor suppressor : getAllSuppressors()) { SuppressedViolation suppressed = suppressor.suppressOrNull(violation, location); if (suppressed != null) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/internal/RuleApplicator.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/internal/RuleApplicator.java index 79deb90e17..ae5a947448 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/internal/RuleApplicator.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/internal/RuleApplicator.java @@ -60,10 +60,10 @@ public class RuleApplicator { try (TimedOperation rcto = TimeTracker.startOperation(TimedOperationCategory.RULE, rule.getName())) { rule.apply(node, ctx); rcto.close(1); - } catch (RuntimeException e) { + } catch (RuntimeException | StackOverflowError | AssertionError e) { // The listener handles logging if needed, // it may also rethrow the error. - listener.onError(new ProcessingError(e, node.getSourceCodeFile())); + listener.onError(new ProcessingError(e, node.getTextDocument().getDisplayName())); } } } finally { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstDocumentNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstDocumentNode.java index b13587fe99..7b4d43da20 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstDocumentNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstDocumentNode.java @@ -23,7 +23,7 @@ import net.sf.saxon.type.Type; /** * See {@link AstTreeInfo#getRootNode()}. */ -class AstDocumentNode extends BaseNodeInfo { +class AstDocumentNode extends BaseNodeInfo implements AstNodeOwner { private final AstElementNode rootElement; private final List children; @@ -68,6 +68,8 @@ class AstDocumentNode extends BaseNodeInfo { @Override public Node getUnderlyingNode() { + // this is a concession to the model, so that the expression "/" + // may be interpreted as the root node return rootElement.getUnderlyingNode(); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstElementNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstElementNode.java index b5debaa918..0fd54c104e 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstElementNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstElementNode.java @@ -37,7 +37,7 @@ import net.sf.saxon.type.Type; * A wrapper for Saxon around a Node. Note: the {@link RootNode} of a tree * corresponds to both a document node and an element node that is its child. */ -public final class AstElementNode extends BaseNodeInfo implements SiblingCountingNode { +public final class AstElementNode extends BaseNodeInfo implements SiblingCountingNode, AstNodeOwner { private final Node wrappedNode; /** The index of the node in the tree according to document order */ diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstNodeOwner.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstNodeOwner.java new file mode 100644 index 0000000000..327d65d5bd --- /dev/null +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/AstNodeOwner.java @@ -0,0 +1,15 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.rule.xpath.internal; + +import net.sourceforge.pmd.lang.ast.Node; + +/** + * Marker interface. + */ +public interface AstNodeOwner { + + Node getUnderlyingNode(); +} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java index 150589ee98..44ecf4abdd 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQuery.java @@ -20,7 +20,6 @@ import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; import net.sourceforge.pmd.lang.rule.xpath.impl.XPathHandler; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.util.DataMap; -import net.sourceforge.pmd.util.DataMap.DataKey; import net.sourceforge.pmd.util.DataMap.SimpleDataKey; import net.sf.saxon.Configuration; @@ -121,17 +120,15 @@ public class SaxonXPathRuleQuery { SequenceIterator iterator = expression.iterate(xpathDynamicContext.getXPathContextObject()); Item current = iterator.next(); while (current != null) { - if (current instanceof AstElementNode) { - results.add(((AstElementNode) current).getUnderlyingNode()); + if (current instanceof AstNodeOwner) { + results.add(((AstNodeOwner) current).getUnderlyingNode()); + } else { + throw new RuntimeException("XPath rule expression returned a non-node (" + current.getClass() + "): " + current); } current = iterator.next(); } } - /* - Map List of Saxon Nodes -> List of AST Nodes, which were detected to match the XPath expression - (i.e. violation found) - */ final List sortedRes = new ArrayList<>(results); sortedRes.sort(RuleChainAnalyzer.documentOrderComparator()); return sortedRes; @@ -170,14 +167,7 @@ public class SaxonXPathRuleQuery { */ private AstTreeInfo getDocumentNodeForRootNode(final Node node) { final RootNode root = node.getRoot(); - - DataMap> userMap = root.getUserMap(); - AstTreeInfo docNode = userMap.get(SAXON_TREE_CACHE_KEY); - if (docNode == null) { - docNode = new AstTreeInfo(root, configuration); - userMap.set(SAXON_TREE_CACHE_KEY, docNode); - } - return docNode; + return root.getUserMap().computeIfAbsent(SAXON_TREE_CACHE_KEY, () -> new AstTreeInfo(root, configuration)); } diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java index 734186243d..2e4d323a11 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/processor/PmdRunnable.java @@ -72,7 +72,7 @@ abstract class PmdRunnable implements Runnable { } else { try { processSource(listener, textDocument, ruleSets); - } catch (Exception e) { + } catch (Exception | StackOverflowError | AssertionError e) { analysisCache.analysisFailed(textDocument); // The listener handles logging if needed, diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java index b96fa57d86..88fc97bcc2 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/renderers/XMLRenderer.java @@ -48,6 +48,7 @@ public class XMLRenderer extends AbstractIncrementingRenderer { private XMLStreamWriter xmlWriter; private OutputStream stream; + private byte[] lineSeparator; public XMLRenderer() { super(NAME, "XML format."); @@ -67,10 +68,11 @@ public class XMLRenderer extends AbstractIncrementingRenderer { @Override public void start() throws IOException { String encoding = getProperty(ENCODING); + lineSeparator = PMD.EOL.getBytes(encoding); try { xmlWriter.writeStartDocument(encoding, "1.0"); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.setDefaultNamespace(PMD_REPORT_NS_URI); xmlWriter.writeStartElement(PMD_REPORT_NS_URI, "pmd"); xmlWriter.writeDefaultNamespace(PMD_REPORT_NS_URI); @@ -86,6 +88,33 @@ public class XMLRenderer extends AbstractIncrementingRenderer { } } + /** + * Outputs a platform dependent line separator. + * + * @throws XMLStreamException if XMLStreamWriter couldn't be flushed. + * @throws IOException if an I/O error occurs. + */ + private void writeNewLine() throws XMLStreamException, IOException { + /* + * Note: we are not using xmlWriter.writeCharacters(PMD.EOL), because some + * XMLStreamWriter implementations might do extra encoding for \r and/or \n. + * Notably IBM's Java 8 will escape "\r" with " " which will render an + * invalid XML document. IBM's Java 8 would also output a platform dependent + * line separator when writing "\n" which results under Windows, that "\r" + * actually is written twice (once escaped, once raw). + * + * Note2: Before writing the raw bytes to the underlying stream, we need + * to flush XMLStreamWriter. Notably IBM's Java 8 might still need to output + * data. + * + * Note3: Before writing the raw bytes, we issue a empty writeCharacters, + * so that any open tags are closed and we are ready for writing raw bytes. + */ + xmlWriter.writeCharacters(""); + xmlWriter.flush(); + stream.write(lineSeparator); + } + @Override public void renderFileViolations(Iterator violations) throws IOException { String filename = null; @@ -102,10 +131,10 @@ public class XMLRenderer extends AbstractIncrementingRenderer { xmlWriter.writeEndElement(); } filename = nextFilename; - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeStartElement("file"); xmlWriter.writeAttribute("name", filename); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); } xmlWriter.writeStartElement("violation"); @@ -121,11 +150,11 @@ public class XMLRenderer extends AbstractIncrementingRenderer { maybeAdd("variable", rv.getVariableName()); maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl()); xmlWriter.writeAttribute("priority", String.valueOf(rv.getRule().getPriority().getPriority())); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeCharacters(StringUtil.removedInvalidXml10Characters(rv.getDescription())); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeEndElement(); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); } if (filename != null) { // Not first file ? xmlWriter.writeEndElement(); @@ -140,20 +169,20 @@ public class XMLRenderer extends AbstractIncrementingRenderer { try { // errors for (Report.ProcessingError pe : errors) { - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeStartElement("error"); xmlWriter.writeAttribute("filename", determineFileName(pe.getFile())); xmlWriter.writeAttribute("msg", pe.getMsg()); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeCData(pe.getDetail()); - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeEndElement(); } // suppressed violations if (showSuppressedViolations) { for (Report.SuppressedViolation s : suppressed) { - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeStartElement("suppressedviolation"); xmlWriter.writeAttribute("filename", determineFileName(s.getRuleViolation().getFilename())); xmlWriter.writeAttribute("suppressiontype", s.getSuppressor().getId().toLowerCase(Locale.ROOT)); @@ -165,14 +194,15 @@ public class XMLRenderer extends AbstractIncrementingRenderer { // config errors for (final Report.ConfigurationError ce : configErrors) { - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeEmptyElement("configerror"); xmlWriter.writeAttribute("rule", ce.rule().getName()); xmlWriter.writeAttribute("msg", ce.issue()); } - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); xmlWriter.writeEndElement(); // - xmlWriter.writeCharacters(PMD.EOL); + writeNewLine(); + xmlWriter.writeEndDocument(); xmlWriter.flush(); } catch (XMLStreamException e) { throw new IOException(e); diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/CompoundIterator.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/CompoundIterator.java deleted file mode 100644 index 0596f3c66f..0000000000 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/CompoundIterator.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.util; - -import java.util.Iterator; -import java.util.NoSuchElementException; - -import net.sourceforge.pmd.annotation.InternalApi; - -/** - * Creates a single compound Iterator from an array of Iterators. - * - * @param - * The type returned by the Iterator. - * - * @see Iterator - */ -@InternalApi -@Deprecated -public class CompoundIterator implements Iterator { - private final Iterator[] iterators; - private int index; - - /** - * - * @param iterators - * The iterators use. - */ - public CompoundIterator(Iterator... iterators) { - this.iterators = iterators; - this.index = 0; - } - - @Override - public boolean hasNext() { - return getNextIterator() != null; - } - - @Override - public T next() { - Iterator iterator = getNextIterator(); - if (iterator != null) { - return iterator.next(); - } else { - throw new NoSuchElementException(); - } - } - - @Override - public void remove() { - Iterator iterator = getNextIterator(); - if (iterator != null) { - iterator.remove(); - } else { - throw new IllegalStateException(); - } - } - - // Get the next iterator with values, returns null if there is no such - // iterator - private Iterator getNextIterator() { - while (index < iterators.length) { - if (iterators[index].hasNext()) { - return iterators[index]; - } else { - index++; - } - } - return null; - } -} diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java index 978fba72ff..d5595cfee4 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/DataMap.java @@ -6,6 +6,9 @@ package net.sourceforge.pmd.util; import java.util.IdentityHashMap; import java.util.Map; +import java.util.function.Supplier; + +import org.checkerframework.checker.nullness.qual.Nullable; /** * An opaque, strongly typed heterogeneous data container. Data maps can @@ -33,7 +36,7 @@ public final class DataMap { * @return Previous value associated with the key (nullable) */ @SuppressWarnings("unchecked") - public T set(DataKey key, T data) { + public @Nullable T set(DataKey key, T data) { return (T) getMap().put(key, data); } @@ -46,10 +49,24 @@ public final class DataMap { * @return Value associated with the key (nullable) */ @SuppressWarnings("unchecked") - public T get(DataKey key) { + public @Nullable T get(DataKey key) { return map == null ? null : (T) map.get(key); } + /** + * Retrieve the value, or compute it if it is missing. + * + * @param key Key + * @param supplier Supplier for a value + * @param Type of the data + * + * @return Value associated with the key (as nullable as the + */ + @SuppressWarnings("unchecked") + public T computeIfAbsent(DataKey key, Supplier supplier) { + return (T) getMap().computeIfAbsent(key, k -> supplier.get()); + } + private Map, Object> getMap() { // the map is lazily created, it's only needed if set() is called // at least once, but get() might be called many more times, as diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/FileLocation.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/FileLocation.java index 1426c06907..b2b7319ca0 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/FileLocation.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/FileLocation.java @@ -95,6 +95,14 @@ public final class FileLocation { return "line " + getBeginLine() + ", column " + getBeginColumn(); } + + /** + * Formats the start position as e.g. {@code "/path/to/file:1:2"}. + */ + public String startPosToStringWithFile() { + return getFileName() + ":" + getBeginLine() + ":" + getBeginColumn(); + } + /** * Creates a new location from the given parameters. * diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextDocument.java b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextDocument.java index 42f8e9c07d..e44d2c3b47 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextDocument.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/util/document/TextDocument.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.util.document; import java.io.Closeable; import java.io.IOException; +import org.apache.commons.io.input.CharSequenceReader; import org.checkerframework.checker.nullness.qual.NonNull; import net.sourceforge.pmd.cpd.SourceCode; diff --git a/pmd-core/src/main/resources/rulesets/releases/41.xml b/pmd-core/src/main/resources/rulesets/releases/41.xml index 50a9b1277b..031efb5aee 100644 --- a/pmd-core/src/main/resources/rulesets/releases/41.xml +++ b/pmd-core/src/main/resources/rulesets/releases/41.xml @@ -21,7 +21,7 @@ This ruleset contains links to rules that are new in PMD v4.1 - + diff --git a/pmd-core/src/main/resources/rulesets/releases/6290.xml b/pmd-core/src/main/resources/rulesets/releases/6290.xml new file mode 100644 index 0000000000..59e64c0e46 --- /dev/null +++ b/pmd-core/src/main/resources/rulesets/releases/6290.xml @@ -0,0 +1,13 @@ + + + + +This ruleset contains links to rules that are new in PMD v6.29.0 + + + + + diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java index 98f91cf160..d2fb3e53a9 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/AbstractRuleTest.java @@ -71,9 +71,9 @@ public class AbstractRuleTest { public void testCreateRV() { MyRule r = new MyRule(); r.setRuleSetName("foo"); - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename"); s.setCoords(5, 5, 5, 10); - RuleViolation rv = new ParametricRuleViolation<>(r, "filename", s, r.getMessage()); + RuleViolation rv = new ParametricRuleViolation<>(r, s, r.getMessage()); assertEquals("Line number mismatch!", 5, rv.getBeginLine()); assertEquals("Filename mismatch!", "filename", rv.getFilename()); assertEquals("Rule object mismatch!", r, rv.getRule()); @@ -84,9 +84,9 @@ public class AbstractRuleTest { @Test public void testCreateRV2() { MyRule r = new MyRule(); - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename"); s.setCoords(5, 5, 5, 10); - RuleViolation rv = new ParametricRuleViolation<>(r, "filename", s, "specificdescription"); + RuleViolation rv = new ParametricRuleViolation<>(r, s, "specificdescription"); assertEquals("Line number mismatch!", 5, rv.getBeginLine()); assertEquals("Filename mismatch!", "filename", rv.getFilename()); assertEquals("Rule object mismatch!", r, rv.getRule()); @@ -117,7 +117,7 @@ public class AbstractRuleTest { Map m = Collections.singletonMap(5, ""); DummyRoot n = new DummyRoot(m); n.setCoords(5, 1, 6, 1); - RuleViolation violation = DefaultRuleViolationFactory.defaultInstance().createViolation(new MyRule(), n, "file", "specificdescription"); + RuleViolation violation = DefaultRuleViolationFactory.defaultInstance().createViolation(new MyRule(), n, "specificdescription"); SuppressedViolation suppressed = DefaultRuleViolationFactory.defaultInstance().suppressOrNull(n, violation); assertNotNull(suppressed); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java index 7dd248cf48..480bdb24a1 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ConfigurationTest.java @@ -19,7 +19,9 @@ import java.nio.charset.StandardCharsets; import java.util.Properties; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import net.sourceforge.pmd.cache.FileAnalysisCache; import net.sourceforge.pmd.cache.NoopAnalysisCache; @@ -29,6 +31,9 @@ import net.sourceforge.pmd.util.ClasspathClassLoader; public class ConfigurationTest { + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Test public void testSuppressMarker() { PMDConfiguration configuration = new PMDConfiguration(); @@ -227,8 +232,7 @@ public class ConfigurationTest { configuration.setAnalysisCache(null); assertNotNull("Default cache was set to null", configuration.getAnalysisCache()); - final File cacheFile = File.createTempFile("pmd-", ".cache"); - cacheFile.deleteOnExit(); + final File cacheFile = folder.newFile(); final FileAnalysisCache analysisCache = new FileAnalysisCache(cacheFile); configuration.setAnalysisCache(analysisCache); assertSame("Configured cache not stored", analysisCache, configuration.getAnalysisCache()); @@ -254,8 +258,7 @@ public class ConfigurationTest { final PMDConfiguration configuration = new PMDConfiguration(); // set dummy cache location - final File cacheFile = File.createTempFile("pmd-", ".cache"); - cacheFile.deleteOnExit(); + final File cacheFile = folder.newFile(); final FileAnalysisCache analysisCache = new FileAnalysisCache(cacheFile); configuration.setAnalysisCache(analysisCache); assertNotNull("Null cache location accepted", configuration.getAnalysisCache()); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java index b111ed9db0..abd4176fe0 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/ReportTest.java @@ -7,14 +7,9 @@ package net.sourceforge.pmd; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.FileInputStream; import java.io.IOException; import java.io.StringWriter; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.commons.io.IOUtils; import org.junit.Test; import net.sourceforge.pmd.lang.ast.DummyNode; @@ -30,12 +25,12 @@ public class ReportTest { @Test public void testSortedReportFile() throws IOException { Report r = new Report(); - Node s = getNode(10, 5); + Node s = getNode(10, 5).withFileName("foo"); Rule rule1 = new MockRule("name", "desc", "msg", "rulesetname"); - r.addRuleViolation(new ParametricRuleViolation<>(rule1, "foo", s, rule1.getMessage())); - Node s1 = getNode(10, 5); + r.addRuleViolation(new ParametricRuleViolation<>(rule1, s, rule1.getMessage())); + Node s1 = getNode(10, 5).withFileName("bar"); Rule rule2 = new MockRule("name", "desc", "msg", "rulesetname"); - r.addRuleViolation(new ParametricRuleViolation<>(rule2, "bar", s1, rule2.getMessage())); + r.addRuleViolation(new ParametricRuleViolation<>(rule2, s1, rule2.getMessage())); Renderer rend = new XMLRenderer(); String result = render(rend, r); assertTrue("sort order wrong", result.indexOf("bar") < result.indexOf("foo")); @@ -44,13 +39,13 @@ public class ReportTest { @Test public void testSortedReportLine() throws IOException { Report r = new Report(); - Node node1 = getNode(20, 5); // line 20: after rule2 violation + Node node1 = getNode(20, 5).withFileName("foo1"); // line 20: after rule2 violation Rule rule1 = new MockRule("rule1", "rule1", "msg", "rulesetname"); - r.addRuleViolation(new ParametricRuleViolation<>(rule1, "foo1", node1, rule1.getMessage())); + r.addRuleViolation(new ParametricRuleViolation<>(rule1, node1, rule1.getMessage())); - Node node2 = getNode(10, 5); // line 10: before rule1 violation + Node node2 = getNode(10, 5).withFileName("foo1"); // line 10: before rule1 violation Rule rule2 = new MockRule("rule2", "rule2", "msg", "rulesetname"); - r.addRuleViolation(new ParametricRuleViolation<>(rule2, "foo1", node2, rule2.getMessage())); // same file!! + r.addRuleViolation(new ParametricRuleViolation<>(rule2, node2, rule2.getMessage())); // same file!! Renderer rend = new XMLRenderer(); String result = render(rend, r); assertTrue("sort order wrong", result.indexOf("rule2") < result.indexOf("rule1")); @@ -61,14 +56,14 @@ public class ReportTest { Report r = new Report(); Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); Node node1 = getNode(5, 5, true); - r.addRuleViolation(new ParametricRuleViolation<>(rule, "", node1, rule.getMessage())); + r.addRuleViolation(new ParametricRuleViolation<>(rule, node1, rule.getMessage())); Node node2 = getNode(5, 6, true); - r.addRuleViolation(new ParametricRuleViolation<>(rule, "", node2, rule.getMessage())); + r.addRuleViolation(new ParametricRuleViolation<>(rule, node2, rule.getMessage())); assertEquals(2, r.getViolations().size()); } - private static Node getNode(int line, int column) { + private static DummyNode getNode(int line, int column) { DummyNode s = new DummyNode(); DummyNode parent = new DummyNode(); parent.setCoords(line, column, line, column + 1); @@ -93,21 +88,4 @@ public class ReportTest { renderer.end(); return writer.toString(); } - - public static String renderTempFile(Renderer renderer, Report report, Charset expectedCharset) throws IOException { - Path tempFile = Files.createTempFile("pmd-report-test", null); - String absolutePath = tempFile.toAbsolutePath().toString(); - - renderer.setReportFile(absolutePath); - renderer.start(); - renderer.renderFileReport(report); - renderer.end(); - renderer.flush(); - - try (FileInputStream input = new FileInputStream(absolutePath)) { - return IOUtils.toString(input, expectedCharset); - } finally { - Files.delete(tempFile); - } - } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleContextTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleContextTest.java index dbcc970c9d..4d313689fa 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleContextTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleContextTest.java @@ -53,4 +53,24 @@ public class RuleContextTest { Assert.assertEquals("message with 1 argument: \"testarg1\"", report.getViolations().get(0).getDescription()); } + + @Test + public void testMessageEscaping() throws Exception { + RuleViolation violation = makeViolation("message with \"'{'\""); + + Assert.assertEquals("message with \"{\"", violation.getDescription()); + } + + @Test + public void testMessageEscaping2() throws Exception { + RuleViolation violation = makeViolation("message with ${ohio}"); + + Assert.assertEquals("message with ${ohio}", violation.getDescription()); + } + + private RuleViolation makeViolation(String unescapedMessage, Object... args) throws Exception { + Report report = getReport(new FooRule(), (r, ctx) -> ctx.addViolationWithMessage(DummyTreeUtil.tree(DummyTreeUtil::root), unescapedMessage, args)); + return report.getViolations().get(0); + } + } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java index f3237d487b..0a4b742df6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetFactoryTest.java @@ -16,7 +16,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Set; import org.apache.commons.lang3.StringUtils; @@ -46,8 +45,7 @@ public class RuleSetFactoryTest { RuleSet rs = loadRuleSet(EMPTY_RULESET); assertNull("RuleSet file name not expected", rs.getFileName()); - RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); - rs = rsf.createRuleSet("net/sourceforge/pmd/TestRuleset1.xml"); + rs = new RuleSetParser().parseFromResource("net/sourceforge/pmd/TestRuleset1.xml"); assertEquals("wrong RuleSet file name", rs.getFileName(), "net/sourceforge/pmd/TestRuleset1.xml"); } @@ -59,8 +57,7 @@ public class RuleSetFactoryTest { @Test public void testRefs() throws Exception { - RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); - RuleSet rs = rsf.createRuleSet("net/sourceforge/pmd/TestRuleset1.xml"); + RuleSet rs = new RuleSetParser().parseFromResource("net/sourceforge/pmd/TestRuleset1.xml"); assertNotNull(rs.getRuleByName("TestRuleRef")); } @@ -70,8 +67,7 @@ public class RuleSetFactoryTest { assertNotNull("Test ruleset not found - can't continue with test!", in); in.close(); - RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); - RuleSets rs = new RuleSets(rsf.createRuleSets("net/sourceforge/pmd/rulesets/reference-ruleset.xml")); + RuleSet rs = new RuleSetParser().parseFromResource("net/sourceforge/pmd/rulesets/reference-ruleset.xml"); // added by referencing a complete ruleset (TestRuleset1.xml) assertNotNull(rs.getRuleByName("MockRule1")); assertNotNull(rs.getRuleByName("MockRule2")); @@ -116,9 +112,9 @@ public class RuleSetFactoryTest { assertEquals(2, ruleset4Rule2.getPriority().getPriority()); } - private int countRule(RuleSets rs, String ruleName) { + private int countRule(RuleSet rs, String ruleName) { int count = 0; - for (Rule r : rs.getAllRules()) { + for (Rule r : rs.getRules()) { if (ruleName.equals(r.getName())) { count++; } @@ -187,8 +183,8 @@ public class RuleSetFactoryTest { + " 2\n \n \n "); - PropertyDescriptor> prop = (PropertyDescriptor>) r.getPropertyDescriptor("packageRegEx"); - List values = r.getProperty(prop); + PropertyDescriptor prop = r.getPropertyDescriptor("packageRegEx"); + Object values = r.getProperty(prop); assertEquals(Arrays.asList("com.aptsssss", "com.abc"), values); } @@ -203,8 +199,8 @@ public class RuleSetFactoryTest { + " value=\"com.aptsssss,com.abc\" \ntype=\"List[String]\" delimiter=\",\" " + "description=\"valid packages\"/>\n" + " " + ""); - PropertyDescriptor> prop = (PropertyDescriptor>) r.getPropertyDescriptor("packageRegEx"); - List values = r.getProperty(prop); + PropertyDescriptor prop = r.getPropertyDescriptor("packageRegEx"); + Object values = r.getProperty(prop); assertEquals(Arrays.asList("com.aptsssss", "com.abc"), values); } @@ -247,12 +243,35 @@ public class RuleSetFactoryTest { } /** - * This is an example of a custom user ruleset, that references a rule, that has been renamed. - * The user should get a deprecation warning. + * This is an example of a category (built-in) ruleset, which contains a rule, that has been renamed. + * This means: a rule definition for "NewName" and a rule reference "OldName", that is deprecated + * and exists for backwards compatibility. + * + *

    When loading this ruleset at a whole for generating the documentation, we should still + * include the deprecated rule reference, so that we can create a nice documentation. * * @throws Exception */ @Test + public void testRuleSetWithDeprecatedRenamedRuleForDoc() throws Exception { + RuleSetParser parser = new RuleSetParser().warnDeprecated(false).includeDeprecatedRuleReferences(true); + RuleSet rs = parser.parseFromResource(createRuleSetReferenceId( + "\n" + "\n" + + " ruleset desc\n" + + " " + + " " + + " d\n" + " 2\n" + " " + + "")); + assertEquals(2, rs.getRules().size()); + assertNotNull(rs.getRuleByName("NewName")); + assertNotNull(rs.getRuleByName("OldName")); + } + + /** + * This is an example of a custom user ruleset, that references a rule, that has been renamed. + * The user should get a deprecation warning. + */ + @Test public void testRuleSetReferencesADeprecatedRenamedRule() throws Exception { RuleSet rs = loadRuleSetWithDeprecationWarnings("\n" + "\n" + " ruleset desc\n" @@ -471,49 +490,50 @@ public class RuleSetFactoryTest { @Test public void testReferencePriority() throws RuleSetNotFoundException { - ResourceLoader rl = new ResourceLoader(); - RuleSetFactory rsf = new RuleSetFactory(rl, RulePriority.LOW, false, true); + RuleSetParser parser = new RuleSetParser().warnDeprecated(false).enableCompatibility(true); + RuleSet ruleSet; - RuleSet ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); - assertEquals("Number of Rules", 3, ruleSet.getRules().size()); - assertNotNull(ruleSet.getRuleByName("MockRuleName")); - assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); - assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); + { + final RuleSetReferenceId refInternalInternal = createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); - ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); - assertEquals("Number of Rules", 2, ruleSet.getRules().size()); - assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); - assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); + ruleSet = parser.filterAbovePriority(RulePriority.LOW).parseFromResource(refInternalInternal); + assertEquals("Number of Rules", 3, ruleSet.getRules().size()); + assertNotNull(ruleSet.getRuleByName("MockRuleName")); + assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); + assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.HIGH, false, true); - ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN)); - assertEquals("Number of Rules", 1, ruleSet.getRules().size()); - assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); + ruleSet = parser.filterAbovePriority(RulePriority.MEDIUM_HIGH).parseFromResource(refInternalInternal); + assertEquals("Number of Rules", 2, ruleSet.getRules().size()); + assertNotNull(ruleSet.getRuleByName("MockRuleNameRef")); + assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.LOW, false, true); - ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); + ruleSet = parser.filterAbovePriority(RulePriority.HIGH).parseFromResource(refInternalInternal); + assertEquals("Number of Rules", 1, ruleSet.getRules().size()); + assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef")); + } + + final RuleSetReferenceId refInternalToExternal = createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN); + + ruleSet = parser.filterAbovePriority(RulePriority.LOW).parseFromResource(refInternalToExternal); assertEquals("Number of Rules", 3, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleName")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); - ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); + ruleSet = parser.filterAbovePriority(RulePriority.MEDIUM_HIGH).parseFromResource(refInternalToExternal); assertEquals("Number of Rules", 2, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef")); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); - rsf = new RuleSetFactory(rl, RulePriority.HIGH, false, true); - ruleSet = rsf.createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN)); + ruleSet = parser.filterAbovePriority(RulePriority.HIGH).parseFromResource(refInternalToExternal); assertEquals("Number of Rules", 1, ruleSet.getRules().size()); assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef")); } @Test public void testOverridePriorityLoadWithMinimum() throws RuleSetNotFoundException { - RuleSetFactory rsf = new RuleSetFactory(new ResourceLoader(), RulePriority.MEDIUM_LOW, true, true); - RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); + RuleSetParser parser = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_LOW).warnDeprecated(true).enableCompatibility(true); + RuleSet ruleset = parser.parseFromResource("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); // only one rule should remain, since we filter out the other rule by minimum priority assertEquals("Number of Rules", 1, ruleset.getRules().size()); @@ -524,8 +544,8 @@ public class RuleSetFactoryTest { assertNotNull(ruleset.getRuleByName("SampleXPathRule")); // now, load with default minimum priority - rsf = RulesetsFactoryUtils.defaultFactory(); - ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); + parser = new RuleSetParser(); + ruleset = parser.parseFromResource("net/sourceforge/pmd/rulesets/ruleset-minimum-priority.xml"); assertEquals("Number of Rules", 2, ruleset.getRules().size()); Rule dummyBasicMockRule = ruleset.getRuleByName("DummyBasicMockRule"); assertEquals("Wrong Priority", RulePriority.LOW, dummyBasicMockRule.getPriority()); @@ -533,14 +553,14 @@ public class RuleSetFactoryTest { @Test public void testExcludeWithMinimumPriority() throws RuleSetNotFoundException { - RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.HIGH, true, true); - RuleSet ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); + RuleSetParser parser = new RuleSetParser().filterAbovePriority(RulePriority.HIGH); + RuleSet ruleset = parser.parseFromResource("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // no rules should be loaded assertEquals("Number of Rules", 0, ruleset.getRules().size()); // now, load with default minimum priority - rsf = RulesetsFactoryUtils.defaultFactory(); - ruleset = rsf.createRuleSet("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); + parser.filterAbovePriority(RulePriority.LOW); + ruleset = parser.parseFromResource("net/sourceforge/pmd/rulesets/ruleset-minimum-priority-exclusion.xml"); // only one rule, we have excluded one... assertEquals("Number of Rules", 1, ruleset.getRules().size()); // rule is excluded @@ -568,11 +588,10 @@ public class RuleSetFactoryTest { @Test public void testSetPriority() throws RuleSetNotFoundException { - ResourceLoader rl = new ResourceLoader(); - RuleSetFactory rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_HIGH, false, true); - assertEquals(0, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); - rsf = new RuleSetFactory(rl, RulePriority.MEDIUM_LOW, false, true); - assertEquals(1, rsf.createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size()); + RuleSetParser rsf = new RuleSetParser().filterAbovePriority(RulePriority.MEDIUM_HIGH); + assertEquals(0, rsf.parseFromResource(createRuleSetReferenceId(SINGLE_RULE)).size()); + rsf.filterAbovePriority(RulePriority.MEDIUM_LOW); + assertEquals(1, rsf.parseFromResource(createRuleSetReferenceId(SINGLE_RULE)).size()); } @Test @@ -750,7 +769,7 @@ public class RuleSetFactoryTest { + " Ruleset which references a empty ruleset\n" + "\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, true); + RuleSetFactory ruleSetFactory = new RuleSetParser().loadResourcesWith(new ResourceLoader()).filterAbovePriority(RulePriority.LOW).warnDeprecated(true).enableCompatibility(true).toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet(ref); assertEquals(0, ruleset.getRules().size()); @@ -772,8 +791,7 @@ public class RuleSetFactoryTest { + " xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd\">\n" + " Custom ruleset for tests\n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - ruleSetFactory.createRuleSet(ref); + new RuleSetParser().parseFromResource(ref); } /** @@ -792,8 +810,7 @@ public class RuleSetFactoryTest { + " PMD Plugin preferences rule set\n" + "\n" + "\n" + "\n" + "\n" + ""); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - RuleSet rs = ruleSetFactory.createRuleSet(ref); + RuleSet rs = new RuleSetParser().parseFromResource(ref); Rule r = rs.getRules().toArray(new Rule[1])[0]; assertEquals("OverriddenDummyBasicMockRule", r.getName()); @@ -819,8 +836,7 @@ public class RuleSetFactoryTest { + " Custom ruleset for tests\n" + " \n" + " \n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - RuleSet ruleset = ruleSetFactory.createRuleSet(ref); + RuleSet ruleset = new RuleSetParser().parseFromResource(ref); assertEquals(4, ruleset.getRules().size()); } @@ -849,8 +865,7 @@ public class RuleSetFactoryTest { + " Custom ruleset for tests\n" + " \n" + " \n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - RuleSet ruleset = ruleSetFactory.createRuleSet(ref1); + RuleSet ruleset = new RuleSetParser().parseFromResource(ref1); assertNull(ruleset.getRuleByName("DummyBasicMockRule")); RuleSetReferenceId ref2 = createRuleSetReferenceId( @@ -861,8 +876,7 @@ public class RuleSetFactoryTest { + " Custom ruleset for tests\n" + " \n" + " \n" + " \n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory2 = RulesetsFactoryUtils.defaultFactory(); - RuleSet ruleset2 = ruleSetFactory2.createRuleSet(ref2); + RuleSet ruleset2 = new RuleSetParser().parseFromResource(ref2); assertNotNull(ruleset2.getRuleByName("DummyBasicMockRule")); RuleSetReferenceId ref3 = createRuleSetReferenceId( @@ -873,8 +887,7 @@ public class RuleSetFactoryTest { + " Custom ruleset for tests\n" + " \n" + " \n" + " \n" + " \n" + "\n"); - RuleSetFactory ruleSetFactory3 = RulesetsFactoryUtils.defaultFactory(); - RuleSet ruleset3 = ruleSetFactory3.createRuleSet(ref3); + RuleSet ruleset3 = new RuleSetParser().parseFromResource(ref3); assertNotNull(ruleset3.getRuleByName("DummyBasicMockRule")); } @@ -891,8 +904,7 @@ public class RuleSetFactoryTest { + " Custom ruleset for tests\n" + " \n" + " \n"); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - ruleSetFactory.createRuleSet(ref); + new RuleSetParser().parseFromResource(ref); assertTrue(logging.getLog().contains("RuleSet name is missing.")); } @@ -906,8 +918,7 @@ public class RuleSetFactoryTest { + " xsi:schemaLocation=\"http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd\">\n" + " \n" + " \n"); - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - ruleSetFactory.createRuleSet(ref); + new RuleSetParser().parseFromResource(ref); assertTrue(logging.getLog().contains("RuleSet description is missing.")); } @@ -1255,7 +1266,7 @@ public class RuleSetFactoryTest { } private RuleSet loadRuleSetWithDeprecationWarnings(String ruleSetXml) throws RuleSetNotFoundException { - RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.LOW, true, false); + RuleSetFactory rsf = new RuleSetParser().warnDeprecated(true).enableCompatibility(false).toFactory(); return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml)); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java index 1854a8bf73..4b8625f121 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetTest.java @@ -25,6 +25,7 @@ import java.util.Random; import java.util.Set; import java.util.regex.Pattern; +import org.apache.commons.io.FilenameUtils; import org.checkerframework.checker.nullness.qual.NonNull; import org.junit.Test; @@ -78,21 +79,21 @@ public class RuleSetTest { @Test public void testGetRuleByName() { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertEquals("unable to fetch rule by name", mock, rs.getRuleByName("name")); } @Test public void testGetRuleByName2() { MockRule mock = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet rs = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(mock); + RuleSet rs = RuleSet.forSingleRule(mock); assertNull("the rule FooRule must not be found!", rs.getRuleByName("FooRule")); } @Test public void testRuleList() { MockRule rule = new MockRule("name", "desc", "msg", "rulesetname"); - RuleSet ruleset = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleset = RuleSet.forSingleRule(rule); assertEquals("Size of RuleSet isn't one.", 1, ruleset.size()); @@ -506,13 +507,17 @@ public class RuleSetTest { } }).build(); - Report report = RuleContextTest.getReportForRuleSetApply(ruleset, makeCompilationUnits()); + Report report = RuleContextTest.getReportForRuleSetApply(ruleset, makeCompilationUnits("samplefile.dummy")); List errors = report.getProcessingErrors(); assertFalse("Report should have processing errors", errors.isEmpty()); assertEquals("Errors expected", 1, errors.size()); - assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", errors.get(0).getMsg()); - assertTrue("Should be a RuntimeException", errors.get(0).getError() instanceof RuntimeException); + ProcessingError processingError = errors.get(0); + assertEquals("Wrong error message", "RuntimeException: Test exception while applying rule", processingError.getMsg()); + assertTrue("Should be a RuntimeException", processingError.getError() instanceof RuntimeException); + assertEquals("Wrong filename in processing error", + "samplefile.dummy", + FilenameUtils.normalize(processingError.getFile(), true)); assertEquals("There should be a violation", 1, report.getViolations().size()); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java index d488f30fcc..6f6e1643dc 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleSetWriterTest.java @@ -81,7 +81,7 @@ public class RuleSetWriterTest { ruleRef.setRuleSetReference(ruleSetReference); ruleRef.setName("Foo"); // override the name - RuleSet ruleSet = ruleSetFactory.createSingleRuleRuleSet(ruleRef); + RuleSet ruleSet = RuleSet.forSingleRule(ruleRef); writer.write(ruleSet); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationComparatorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationComparatorTest.java index d105e2b4a6..01d69e9853 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationComparatorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationComparatorTest.java @@ -70,8 +70,8 @@ public class RuleViolationComparatorTest { private RuleViolation createJavaRuleViolation(Rule rule, String fileName, int beginLine, String description, int beginColumn, int endLine, int endColumn) { - DummyNode simpleNode = new DummyNode(); + DummyNode simpleNode = new DummyNode().withFileName(fileName); simpleNode.setCoords(beginLine, beginColumn, endLine, endColumn); - return new ParametricRuleViolation(rule, fileName, simpleNode, description); + return new ParametricRuleViolation(rule, simpleNode, description); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationTest.java index 44cfbf739d..b00cf3b247 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/RuleViolationTest.java @@ -24,9 +24,9 @@ public class RuleViolationTest { @Test public void testConstructor1() { Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename"); s.setCoords(2, 1, 2, 3); - RuleViolation r = new ParametricRuleViolation(rule, "filename", s, rule.getMessage()); + RuleViolation r = new ParametricRuleViolation(rule, s, rule.getMessage()); assertEquals("object mismatch", rule, r.getRule()); assertEquals("line number is wrong", 2, r.getBeginLine()); assertEquals("filename is wrong", "filename", r.getFilename()); @@ -35,9 +35,9 @@ public class RuleViolationTest { @Test public void testConstructor2() { Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename"); s.setCoords(2, 1, 2, 3); - RuleViolation r = new ParametricRuleViolation(rule, "filename", s, "description"); + RuleViolation r = new ParametricRuleViolation(rule, s, "description"); assertEquals("object mismatch", rule, r.getRule()); assertEquals("line number is wrong", 2, r.getBeginLine()); assertEquals("filename is wrong", "filename", r.getFilename()); @@ -48,12 +48,12 @@ public class RuleViolationTest { public void testComparatorWithDifferentFilenames() { Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); Comparator comp = RuleViolation.DEFAULT_COMPARATOR; - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename1"); s.setCoords(10, 1, 11, 3); - RuleViolation r1 = new ParametricRuleViolation(rule, "filename1", s, "description"); - DummyNode s1 = new DummyNode(); + RuleViolation r1 = new ParametricRuleViolation(rule, s, "description"); + DummyNode s1 = new DummyNode().withFileName("filename2"); s1.setCoords(10, 1, 11, 3); - RuleViolation r2 = new ParametricRuleViolation(rule, "filename2", s1, "description"); + RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description"); assertEquals(-1, comp.compare(r1, r2)); assertEquals(1, comp.compare(r2, r1)); } @@ -62,12 +62,12 @@ public class RuleViolationTest { public void testComparatorWithSameFileDifferentLines() { Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); Comparator comp = RuleViolation.DEFAULT_COMPARATOR; - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename1"); s.setCoords(10, 1, 15, 10); - DummyNode s1 = new DummyNode(); + DummyNode s1 = new DummyNode().withFileName("filename1"); s1.setCoords(20, 1, 25, 10); - RuleViolation r1 = new ParametricRuleViolation(rule, "filename", s, "description"); - RuleViolation r2 = new ParametricRuleViolation(rule, "filename", s1, "description"); + RuleViolation r1 = new ParametricRuleViolation(rule, s, "description"); + RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description"); assertTrue(comp.compare(r1, r2) < 0); assertTrue(comp.compare(r2, r1) > 0); } @@ -77,12 +77,12 @@ public class RuleViolationTest { public void testComparatorWithSameFileSameLines() { Rule rule = new MockRule("name", "desc", "msg", "rulesetname"); Comparator comp = RuleViolation.DEFAULT_COMPARATOR; - DummyNode s = new DummyNode(); + DummyNode s = new DummyNode().withFileName("filename1"); s.setCoords(10, 1, 15, 10); - DummyNode s1 = new DummyNode(); + DummyNode s1 = new DummyNode().withFileName("filename1"); s.setCoords(10, 1, 15, 10); - RuleViolation r1 = new ParametricRuleViolation(rule, "filename", s, "description"); - RuleViolation r2 = new ParametricRuleViolation(rule, "filename", s1, "description"); + RuleViolation r1 = new ParametricRuleViolation(rule, s, "description"); + RuleViolation r2 = new ParametricRuleViolation(rule, s1, "description"); assertEquals(1, comp.compare(r1, r2)); assertEquals(1, comp.compare(r2, r1)); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java index 37358b94f2..39940f6d9f 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/DummyLanguageModule.java @@ -61,8 +61,8 @@ public class DummyLanguageModule extends BaseLanguageModule { public static class RuleViolationFactory extends DefaultRuleViolationFactory { @Override - public RuleViolation createViolation(Rule rule, @NonNull Node location, String filename, String formattedMessage) { - return new ParametricRuleViolation(rule, filename, location, formattedMessage) { + public RuleViolation createViolation(Rule rule, @NonNull Node location, @NonNull String formattedMessage) { + return new ParametricRuleViolation(rule, location, formattedMessage) { { this.packageName = "foo"; // just for testing variable expansion } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java index dde5b604c7..69d6636d3e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyNode.java @@ -7,15 +7,19 @@ package net.sourceforge.pmd.lang.ast; import java.util.HashMap; import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; + import net.sourceforge.pmd.lang.ast.impl.AbstractNode; import net.sourceforge.pmd.lang.ast.impl.GenericNode; import net.sourceforge.pmd.util.document.FileLocation; +import net.sourceforge.pmd.util.document.TextDocument; public class DummyNode extends AbstractNode implements GenericNode { private final boolean findBoundary; private final String xpathName; private final Map userData = new HashMap<>(); private String image; + private String fileName = "sample.dummy"; private FileLocation location; @@ -59,6 +63,18 @@ public class DummyNode extends AbstractNode implements Gen this.image = image; } + public DummyNode withFileName(String fname) { + this.fileName = fname; + return this; + } + + + @Override + public @NonNull TextDocument getTextDocument() { + return TextDocument.readOnlyString("dummy text", fileName, getRoot().getLanguageVersion()); + } + + @Override public String getImage() { return image; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyRoot.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyRoot.java index 52e5260181..123904ca5e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyRoot.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/ast/DummyRoot.java @@ -7,19 +7,15 @@ package net.sourceforge.pmd.lang.ast; import java.util.Collections; import java.util.Map; -import org.checkerframework.checker.nullness.qual.NonNull; - import net.sourceforge.pmd.lang.DummyLanguageModule; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.impl.GenericNode; -import net.sourceforge.pmd.util.document.TextDocument; public class DummyRoot extends DummyNode implements GenericNode, RootNode { private final Map suppressMap; private LanguageVersion languageVersion; - private String filename = "sample.dummy"; public DummyRoot(Map suppressMap, LanguageVersion languageVersion) { super(); @@ -41,21 +37,21 @@ public class DummyRoot extends DummyNode implements GenericNode, Root } + @Override + public LanguageVersion getLanguageVersion() { + return languageVersion; + } + public DummyRoot withLanguage(LanguageVersion languageVersion) { this.languageVersion = languageVersion; return this; } public DummyRoot withFileName(String filename) { - this.filename = filename; + super.withFileName(filename); return this; } - @Override - public @NonNull TextDocument getTextDocument() { - return TextDocument.readOnlyString("dummy text", filename, languageVersion); - } - @Override public Map getNoPmdComments() { return suppressMap; diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/DefaultRuleViolationFactoryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/DefaultRuleViolationFactoryTest.java deleted file mode 100644 index be4976ee99..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/DefaultRuleViolationFactoryTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.rule; - -import org.junit.Assert; -import org.junit.Test; - -import net.sourceforge.pmd.RuleContext; -import net.sourceforge.pmd.RuleViolation; -import net.sourceforge.pmd.lang.ast.DummyRoot; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.impl.DummyTreeUtil; -import net.sourceforge.pmd.lang.rule.impl.DefaultRuleViolationFactory; - -public class DefaultRuleViolationFactoryTest { - - private static class TestRule extends AbstractRule { - @Override - public void apply(Node target, RuleContext ctx) { - throw new UnsupportedOperationException("not implemented"); - } - } - - @Test - public void testMessage() { - RuleViolation violation = DefaultRuleViolationFactory.defaultInstance().createViolation(new TestRule(), DummyTreeUtil.tree(DummyRoot::new), "file", "Some message"); - - Assert.assertEquals("Some message", violation.getDescription()); - } - -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java index dd128e7690..d34335a1e6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/internal/SaxonXPathRuleQueryTest.java @@ -16,8 +16,11 @@ import java.util.List; import java.util.Map; import org.checkerframework.checker.nullness.qual.NonNull; +import org.hamcrest.CoreMatchers; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import net.sourceforge.pmd.lang.ast.DummyNodeWithListAndEnum; import net.sourceforge.pmd.lang.ast.DummyRoot; @@ -39,6 +42,9 @@ import net.sf.saxon.value.SequenceType; public class SaxonXPathRuleQueryTest { + @Rule + public final ExpectedException expected = ExpectedException.none(); + // Unsupported: https://github.com/pmd/pmd/issues/2451 // @Test // public void testListAttribute() { @@ -95,6 +101,45 @@ public class SaxonXPathRuleQueryTest { assertQuery(1, "//dummyRootNode[@Enum = $prop]", dummy, prop); } + @Test + public void testInvalidReturn() { + DummyNodeWithListAndEnum dummy = new DummyNodeWithListAndEnum(); + + + expected.expect(RuntimeException.class); + expected.expectMessage(CoreMatchers.containsString("XPath rule expression returned a non-node")); + expected.expectMessage(CoreMatchers.containsString("Int64Value")); + + createQuery("1+2").evaluate(dummy); + } + + @Test + public void testRootExpression() { + DummyRoot dummy = new DummyRoot(); + + List result = assertQuery(1, "/", dummy); + Assert.assertEquals(dummy, result.get(0)); + } + + @Test + public void testRootExpressionIsADocumentNode() { + DummyRoot dummy = new DummyRoot(); + + List result = assertQuery(1, "(/)[self::document-node()]", dummy); + Assert.assertEquals(dummy, result.get(0)); + } + + @Test + public void testRootExpressionWithName() { + DummyRoot dummy = new DummyRoot(); + String xpathName = dummy.getXPathNodeName(); + + List result = assertQuery(1, "(/)[self::document-node(element(" + xpathName + "))]", dummy); + Assert.assertEquals(dummy, result.get(0)); + + assertQuery(0, "(/)[self::document-node(element(DummyNodeX))]", dummy); + } + @Test public void ruleChainVisits() { SaxonXPathRuleQuery query = createQuery("//dummyNode[@Image='baz']/foo | //bar[@Public = 'true'] | //dummyNode[@Public = false()] | //dummyNode"); @@ -288,10 +333,11 @@ public class SaxonXPathRuleQueryTest { .replaceAll("\\$zz:zz-?\\d+", "\\$zz:zz000"); } - private static void assertQuery(int resultSize, String xpath, Node node, PropertyDescriptor... descriptors) { + private static List assertQuery(int resultSize, String xpath, Node node, PropertyDescriptor... descriptors) { SaxonXPathRuleQuery query = createQuery(xpath, descriptors); List result = query.evaluate(node); assertEquals("Wrong number of matched nodes", resultSize, result.size()); + return result; } private static SaxonXPathRuleQuery createQuery(String xpath, PropertyDescriptor... descriptors) { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/processor/GlobalListenerTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/processor/GlobalListenerTest.java index c93dcf62db..dde363e8e1 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/processor/GlobalListenerTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/processor/GlobalListenerTest.java @@ -167,7 +167,7 @@ public class GlobalListenerTest { @Override public void apply(Node node, RuleContext ctx) { - if (node.getSourceCodeFile().contains("1")) { + if (node.getTextDocument().getDisplayName().contains("1")) { addViolation(ctx, node); } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/processor/MultiThreadProcessorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/processor/MultiThreadProcessorTest.java index 11fcbf13d6..01510c9032 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/processor/MultiThreadProcessorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/processor/MultiThreadProcessorTest.java @@ -98,7 +98,7 @@ public class MultiThreadProcessorTest { public void apply(Node target, RuleContext ctx) { count.incrementAndGet(); - if (target.getSourceCodeFile().contains("violation")) { + if (target.getTextDocument().getDisplayName().contains("violation")) { hasViolation = true; } else { letTheOtherThreadRun(10); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java index c6276c5ddc..3995a91c1f 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/properties/PropertyDescriptorTest.java @@ -32,7 +32,6 @@ import org.junit.rules.ExpectedException; import net.sourceforge.pmd.FooRule; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; -import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.properties.constraints.PropertyConstraint; @@ -59,7 +58,7 @@ public class PropertyDescriptorTest { FooRule rule = new FooRule(); rule.definePropertyDescriptor(intProperty); rule.setProperty(intProperty, 1000); - RuleSet ruleSet = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleSet = RuleSet.forSingleRule(rule); List dysfunctional = new ArrayList<>(); ruleSet.removeDysfunctionalRules(dysfunctional); @@ -80,7 +79,7 @@ public class PropertyDescriptorTest { FooRule rule = new FooRule(); rule.definePropertyDescriptor(descriptor); rule.setProperty(descriptor, Collections.singletonList(1000d)); // not in range - RuleSet ruleSet = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule); + RuleSet ruleSet = RuleSet.forSingleRule(rule); List dysfunctional = new ArrayList<>(); ruleSet.removeDysfunctionalRules(dysfunctional); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java index f8071db9f0..a50d7a96d6 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/AbstractRendererTest.java @@ -73,11 +73,11 @@ public abstract class AbstractRendererTest { protected RuleViolation newRuleViolation(int endColumn) { DummyNode node = createNode(endColumn); - return new ParametricRuleViolation(new FooRule(), getSourceCodeFilename(), node, "blah"); + return new ParametricRuleViolation(new FooRule(), node, "blah"); } - protected static DummyNode createNode(int endColumn) { - DummyNode node = new DummyNode(); + protected DummyNode createNode(int endColumn) { + DummyNode node = new DummyNode().withFileName(getSourceCodeFilename()); node.setCoords(1, 1, 1, endColumn); return node; } @@ -89,7 +89,7 @@ public abstract class AbstractRendererTest { RuleWithProperties theRule = new RuleWithProperties(); theRule.setProperty(RuleWithProperties.STRING_PROPERTY_DESCRIPTOR, "the string value\nsecond line with \"quotes\""); - report.addRuleViolation(new ParametricRuleViolation(theRule, getSourceCodeFilename(), node, "blah")); + report.addRuleViolation(new ParametricRuleViolation(theRule, node, "blah")); String rendered = ReportTest.render(getRenderer(), report); assertEquals(filter(getExpectedWithProperties()), filter(rendered)); } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java index 217a7ce240..8713ceaa1e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/CodeClimateRendererTest.java @@ -96,7 +96,7 @@ public class CodeClimateRendererTest extends AbstractRendererTest { theRule.setDescription("desc"); theRule.setName("Foo"); - report.addRuleViolation(new ParametricRuleViolation(theRule, getSourceCodeFilename(), node, "blah")); + report.addRuleViolation(new ParametricRuleViolation(theRule, node, "blah")); String rendered = ReportTest.render(getRenderer(), report); // Output should be the exact same as for non xpath rules diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SummaryHTMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SummaryHTMLRendererTest.java index 42c5f3fd87..eeb5d465a1 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SummaryHTMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/SummaryHTMLRendererTest.java @@ -130,7 +130,7 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest { + PMD.EOL + "#FileLineProblem" + PMD.EOL + "


    Suppressed warnings

    " + PMD.EOL + "" - + PMD.EOL + " " + PMD.EOL + "" + PMD.EOL + + PMD.EOL + " " + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" + PMD.EOL + "" @@ -148,7 +148,7 @@ public class SummaryHTMLRendererTest extends AbstractRendererTest { private Report createEmptyReportWithSuppression() throws Exception { - DummyRoot root = new DummyRoot(Collections.singletonMap(1, "test")).withFileName(""); + DummyRoot root = new DummyRoot(Collections.singletonMap(1, "test")).withFileName(getSourceCodeFilename()); root.setCoords(1, 10, 4, 5); return RuleContextTest.getReportForRuleApply(new FooRule() { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java index 44cbd72c8b..c88f8c4ffe 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XMLRendererTest.java @@ -4,15 +4,20 @@ package net.sourceforge.pmd.renderers; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.rules.TemporaryFolder; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; @@ -23,7 +28,6 @@ import net.sourceforge.pmd.PMDVersion; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Report.ConfigurationError; import net.sourceforge.pmd.Report.ProcessingError; -import net.sourceforge.pmd.ReportTest; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.lang.ast.DummyNode; import net.sourceforge.pmd.lang.ast.Node; @@ -33,6 +37,9 @@ public class XMLRendererTest extends AbstractRendererTest { @Rule // Restores system properties after test public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Override public Renderer getRenderer() { return new XMLRenderer(); @@ -83,9 +90,9 @@ public class XMLRendererTest extends AbstractRendererTest { } private RuleViolation createRuleViolation(String description) { - DummyNode node = new DummyNode(); + DummyNode node = new DummyNode().withFileName(getSourceCodeFilename()); node.setCoords(1, 1, 1, 1); - return new ParametricRuleViolation(new FooRule(), getSourceCodeFilename(), node, description); + return new ParametricRuleViolation(new FooRule(), node, description); } private void verifyXmlEscaping(Renderer renderer, String shouldContain, Charset charset) throws Exception { @@ -94,7 +101,7 @@ public class XMLRendererTest extends AbstractRendererTest { String surrogatePair = "\ud801\udc1c"; String msg = "The String 'literal' \"TokénizĀr " + surrogatePair + "\" appears..."; report.addRuleViolation(createRuleViolation(msg)); - String actual = ReportTest.renderTempFile(renderer, report, charset); + String actual = renderTempFile(renderer, report, charset); Assert.assertTrue(actual.contains(shouldContain)); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new InputSource(new StringReader(actual))); @@ -137,7 +144,7 @@ public class XMLRendererTest extends AbstractRendererTest { String originalChars = formFeed + specialChars; // u000C should be removed, é should be encoded correctly as UTF-8 String msg = "The String literal \"" + originalChars + "\" appears..."; report.addRuleViolation(createRuleViolation(msg)); - String actual = ReportTest.renderTempFile(renderer, report, StandardCharsets.UTF_8); + String actual = renderTempFile(renderer, report, StandardCharsets.UTF_8); Assert.assertTrue(actual.contains(specialChars)); Assert.assertFalse(actual.contains(formFeed)); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() @@ -146,4 +153,18 @@ public class XMLRendererTest extends AbstractRendererTest { Assert.assertEquals(1, violations.getLength()); Assert.assertEquals(msg.replaceAll(formFeed, ""), violations.item(0).getTextContent().trim()); } + + private String renderTempFile(Renderer renderer, Report report, Charset expectedCharset) throws IOException { + File reportFile = folder.newFile(); + + renderer.setReportFile(reportFile.getAbsolutePath()); + renderer.start(); + renderer.renderFileReport(report); + renderer.end(); + renderer.flush(); + + try (FileInputStream input = new FileInputStream(reportFile)) { + return IOUtils.toString(input, expectedCharset); + } + } } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XSLTRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XSLTRendererTest.java index 98b79111f3..5c1c5bbcdc 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XSLTRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/XSLTRendererTest.java @@ -21,9 +21,9 @@ public class XSLTRendererTest { public void testDefaultStylesheet() throws Exception { XSLTRenderer renderer = new XSLTRenderer(); Report report = new Report(); - DummyNode node = new DummyNode(); + DummyNode node = new DummyNode().withFileName("file"); node.setCoords(1, 1, 1, 2); - RuleViolation rv = new ParametricRuleViolation(new FooRule(), "file", node, "violation message"); + RuleViolation rv = new ParametricRuleViolation(new FooRule(), node, "violation message"); report.addRuleViolation(rv); String result = ReportTest.render(renderer, report); Assert.assertTrue(result.contains("violation message")); diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java index 141d8452c7..6062e3f457 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/renderers/YAHTMLRendererTest.java @@ -15,9 +15,10 @@ import java.util.Arrays; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import net.sourceforge.pmd.FooRule; import net.sourceforge.pmd.PMD; @@ -32,44 +33,19 @@ import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; public class YAHTMLRendererTest extends AbstractRendererTest { - private String outputDir; + private File outputDir; + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); @Before public void setUp() throws IOException { - outputDir = getTemporaryDirectory("pmdtest").getAbsolutePath(); - } - - @After - public void cleanUp() { - deleteDirectory(new File(outputDir)); - } - - private File getTemporaryDirectory(String prefix) throws IOException { - // TODO: move to util class? - File dir = File.createTempFile(prefix, ""); - dir.delete(); - dir.mkdir(); - return dir; - } - - private void deleteDirectory(File dir) { - // TODO: move to util class? - File[] a = dir.listFiles(); - if (a != null) { - for (File f : a) { - if (f.isDirectory()) { - deleteDirectory(f); - } else { - f.delete(); - } - } - } - dir.delete(); + outputDir = folder.newFolder("pmdtest"); } private RuleViolation newRuleViolation(int endColumn, final String packageNameArg, final String classNameArg) { DummyNode node = createNode(endColumn); - return new ParametricRuleViolation(new FooRule(), getSourceCodeFilename(), node, "blah") { + return new ParametricRuleViolation(new FooRule(), node, "blah") { { packageName = packageNameArg; className = classNameArg; @@ -91,7 +67,7 @@ public class YAHTMLRendererTest extends AbstractRendererTest { String actual = ReportTest.render(getRenderer(), report); assertEquals(filter(getExpected()), filter(actual)); - String[] htmlFiles = new File(outputDir).list(); + String[] htmlFiles = outputDir.list(); assertEquals(3, htmlFiles.length); Arrays.sort(htmlFiles); assertEquals("YAHTMLSampleClass1.html", htmlFiles[0]); @@ -117,7 +93,7 @@ public class YAHTMLRendererTest extends AbstractRendererTest { @Override public Renderer getRenderer() { Renderer result = new YAHTMLRenderer(); - result.setProperty(YAHTMLRenderer.OUTPUT_DIR, outputDir); + result.setProperty(YAHTMLRenderer.OUTPUT_DIR, outputDir.getAbsolutePath()); return result; } diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/CompoundListTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/CompoundListTest.java deleted file mode 100644 index 86b41ff4cb..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/util/CompoundListTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.util; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import org.junit.Before; -import org.junit.Test; - -public class CompoundListTest { - - private List l1; - private List l2; - private Iterator iterator; - - @Before - public void setUp() { - l1 = new ArrayList<>(); - l1.add("1"); - l1.add("2"); - l2 = new ArrayList<>(); - l2.add("3"); - l2.add("4"); - - iterator = new CompoundIterator<>(l1.iterator(), l2.iterator()); - } - - @Test - public void testHappyPath() { - assertTrue(iterator.hasNext()); - assertEquals("1", iterator.next()); - assertTrue(iterator.hasNext()); - assertEquals("2", iterator.next()); - assertTrue(iterator.hasNext()); - assertEquals("3", iterator.next()); - assertTrue(iterator.hasNext()); - assertEquals("4", iterator.next()); - assertFalse(iterator.hasNext()); - assertEquals(2, l1.size()); - assertEquals(2, l2.size()); - } - - @Test - public void testHappyPathRemove() { - assertTrue(iterator.hasNext()); - assertEquals("1", iterator.next()); - iterator.remove(); - assertTrue(iterator.hasNext()); - assertEquals("2", iterator.next()); - assertTrue(iterator.hasNext()); - assertEquals("3", iterator.next()); - iterator.remove(); - assertTrue(iterator.hasNext()); - assertEquals("4", iterator.next()); - assertFalse(iterator.hasNext()); - assertEquals(1, l1.size()); - assertEquals("2", l1.get(0)); - assertEquals(1, l2.size()); - assertEquals("4", l2.get(0)); - } - - @Test - public void testEmpty() { - Iterator iterator = new CompoundIterator(); - assertFalse(iterator.hasNext()); - } - - @Test(expected = NoSuchElementException.class) - public void testEmptyBadNext() { - Iterator iterator = new CompoundIterator(); - iterator.next(); - } - - @Test(expected = IllegalStateException.class) - public void testEmptyBadRemove() { - Iterator iterator = new CompoundIterator(); - iterator.remove(); - } - - public static junit.framework.Test suite() { - return new junit.framework.JUnit4TestAdapter(CompoundListTest.class); - } -} diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/util/database/DBTypeTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/util/database/DBTypeTest.java index 2bdd29465f..bba684648e 100644 --- a/pmd-core/src/test/java/net/sourceforge/pmd/util/database/DBTypeTest.java +++ b/pmd-core/src/test/java/net/sourceforge/pmd/util/database/DBTypeTest.java @@ -14,7 +14,9 @@ import java.util.ResourceBundle; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; /** * @@ -27,6 +29,9 @@ public class DBTypeTest { private Properties testProperties; private Properties includeProperties; + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Before public void setUp() throws Exception { testProperties = new Properties(); @@ -38,7 +43,7 @@ public class DBTypeTest { includeProperties.putAll(testProperties); includeProperties.put("prop3", "include3"); - absoluteFile = File.createTempFile("dbtypetest", ".properties"); + absoluteFile = folder.newFile(); try (FileOutputStream fileOutputStream = new FileOutputStream(absoluteFile); PrintStream printStream = new PrintStream(fileOutputStream)) { for (Entry entry : testProperties.entrySet()) { @@ -50,7 +55,6 @@ public class DBTypeTest { @After public void tearDown() throws Exception { testProperties = null; - absoluteFile.delete(); } /** diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AbstractBinaryDistributionTest.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AbstractBinaryDistributionTest.java index 692d40378a..2822d2867a 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AbstractBinaryDistributionTest.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AbstractBinaryDistributionTest.java @@ -5,13 +5,11 @@ package net.sourceforge.pmd.it; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import org.apache.commons.io.FileUtils; -import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.rules.TemporaryFolder; import net.sourceforge.pmd.PMDVersion; @@ -21,6 +19,9 @@ public abstract class AbstractBinaryDistributionTest { return new File(".", "target/pmd-bin-" + PMDVersion.VERSION + ".zip"); } + @ClassRule + public static TemporaryFolder folder = new TemporaryFolder(); + /** * The temporary directory, to which the binary distribution will be extracted. * It will be deleted again after the test. @@ -29,16 +30,9 @@ public abstract class AbstractBinaryDistributionTest { @BeforeClass public static void setupTempDirectory() throws Exception { - tempDir = Files.createTempDirectory("pmd-it-test-"); + tempDir = folder.newFolder().toPath(); if (getBinaryDistribution().exists()) { ZipFileExtractor.extractZipFile(getBinaryDistribution().toPath(), tempDir); } } - - @AfterClass - public static void cleanupTempDirectory() throws IOException { - if (tempDir != null && tempDir.toFile().exists()) { - FileUtils.forceDelete(tempDir.toFile()); - } - } } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java index 19fe9b3519..e485e89a03 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/AllRulesIT.java @@ -31,8 +31,8 @@ public class AllRulesIT extends AbstractBinaryDistributionTest { public void runRuleTests() throws Exception { String srcDir = new File(".", "src/test/resources/sample-source/" + language + "/").getAbsolutePath(); - ExecutionResult result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/all-" - + language + ".xml"); + ExecutionResult result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, + "src/test/resources/rulesets/all-" + language + ".xml"); assertDefaultExecutionResult(result); } diff --git a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java index 8181447b83..ba0ff6637d 100644 --- a/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java +++ b/pmd-dist/src/test/java/net/sourceforge/pmd/it/BinaryDistributionIT.java @@ -80,15 +80,15 @@ public class BinaryDistributionIT extends AbstractBinaryDistributionTest { result = PMDExecutor.runPMD(tempDir, "-h"); result.assertExecutionResult(0, SUPPORTED_LANGUAGES_PMD); - result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml"); + result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml"); result.assertExecutionResult(4, "", "JumbledIncrementer.java:8:"); // also test XML format - result = PMDExecutor.runPMDRules(tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml"); + result = PMDExecutor.runPMDRules(folder.newFile().toPath(), tempDir, srcDir, "src/test/resources/rulesets/sample-ruleset.xml", "xml"); result.assertExecutionResult(4, "", "JumbledIncrementer.java\">"); result.assertExecutionResult(4, "", " registeredRuleSets = ruleSetFactory.getRegisteredRuleSets(); + // important: use a RuleSetFactory that includes all rules, e.g. deprecated rule references + Iterator registeredRuleSets = getRegisteredRuleSets().iterator(); List additionalRulesets = findAdditionalRulesets(output); RuleDocGenerator generator = new RuleDocGenerator(new DefaultFileWriter(), output); @@ -49,12 +56,54 @@ public final class GenerateRuleDocsCmd { System.out.println("Generated docs in " + (System.currentTimeMillis() - start) + " ms"); } + + /** + * Returns an Iterator of RuleSet objects loaded from descriptions from the + * "categories.properties" resource for each Language with Rule support. + * + * @return An Iterator of RuleSet objects. + * + * @throws RuleSetNotFoundException if the ruleset file could not be found + */ + private static Iterable getRegisteredRuleSets() throws RuleSetNotFoundException { + String rulesetsProperties; + RuleSetParser parser = new RuleSetParser().warnDeprecated(false).includeDeprecatedRuleReferences(true); + + List ruleSets = new ArrayList<>(); + for (Language language : LanguageRegistry.getLanguages()) { + Properties props = new Properties(); + rulesetsProperties = "category/" + language.getTerseName() + "/categories.properties"; + + InputStream resource = GenerateRuleDocsCmd.class.getResourceAsStream(rulesetsProperties); + if (resource == null) { + LOG.warning("The language " + language.getTerseName() + " provides no " + rulesetsProperties + "."); + continue; + } + + try (InputStream inputStream = resource) { + props.load(inputStream); + String rulesetFilenames = props.getProperty("rulesets.filenames"); + + if (rulesetFilenames != null) { + + ruleSets.addAll(parser.parseFromResources(rulesetFilenames.split(","))); + + } + } catch (IOException ioe) { + throw new RuntimeException("Couldn't find " + rulesetsProperties + + "; please ensure that the directory is on the classpath. The current classpath is: " + + System.getProperty("java.class.path")); + } + } + return ruleSets; + } + public static List findAdditionalRulesets(Path basePath) { try { List additionalRulesets = new ArrayList<>(); Pattern rulesetPattern = Pattern.compile("^.+" + Pattern.quote(File.separator) + "pmd-\\w+" - + Pattern.quote(FilenameUtils.normalize("/src/main/resources/rulesets/")) - + "\\w+" + Pattern.quote(File.separator) + "\\w+.xml$"); + + Pattern.quote(FilenameUtils.normalize("/src/main/resources/rulesets/")) + + "\\w+" + Pattern.quote(File.separator) + "\\w+.xml$"); Files.walkFileTree(basePath, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { diff --git a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java index 47e3d21f23..5e7561cdf3 100644 --- a/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java +++ b/pmd-doc/src/test/java/net/sourceforge/pmd/docs/RuleDocGeneratorTest.java @@ -9,20 +9,19 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.List; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; -import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; @@ -34,11 +33,14 @@ public class RuleDocGeneratorTest { private MockedFileWriter writer = new MockedFileWriter(); private Path root; + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Before public void setup() throws IOException { writer.reset(); - root = Files.createTempDirectory("pmd-ruledocgenerator-test"); + root = folder.newFolder().toPath(); Files.createDirectories(root.resolve("docs/_data/sidebars")); List mockedSidebar = Arrays.asList( "entries:", @@ -51,23 +53,6 @@ public class RuleDocGeneratorTest { Files.write(root.resolve("docs/_data/sidebars/pmd_sidebar.yml"), mockedSidebar); } - @After - public void cleanup() throws IOException { - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } - private static String loadResource(String name) throws IOException { return MockedFileWriter.normalizeLineSeparators( IOUtils.toString(RuleDocGeneratorTest.class.getResourceAsStream(name), StandardCharsets.UTF_8)); @@ -77,7 +62,7 @@ public class RuleDocGeneratorTest { public void testSingleRuleset() throws RuleSetNotFoundException, IOException { RuleDocGenerator generator = new RuleDocGenerator(writer, root); - RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); + RuleSetFactory rsf = RulesetsFactoryUtils.createFactory(RulePriority.LOW, false, false, true); RuleSet ruleset = rsf.createRuleSet("rulesets/ruledoctest/sample.xml"); generator.generate(Arrays.asList(ruleset).iterator(), diff --git a/pmd-doc/src/test/resources/expected/java.md b/pmd-doc/src/test/resources/expected/java.md index a20c0aa803..0ba141b68c 100644 --- a/pmd-doc/src/test/resources/expected/java.md +++ b/pmd-doc/src/test/resources/expected/java.md @@ -15,7 +15,10 @@ folder: pmd/rules * [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer): Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. * [MovedRule](pmd_rules_java_sample.html#movedrule): Deprecated The rule has been moved to another ruleset. Use instead [JumbledIncrementer](pmd_rules_java_sample2.html#jumbledincrementer). * [OverrideBothEqualsAndHashcode](pmd_rules_java_sample.html#overridebothequalsandhashcode): Override both 'public boolean Object.equals(Object other)', and 'public int Object.hashCode()', o... -* [RenamedRule](pmd_rules_java_sample.html#renamedrule): Deprecated The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). +* [RenamedRule1](pmd_rules_java_sample.html#renamedrule1): Deprecated The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). +* [RenamedRule2](pmd_rules_java_sample.html#renamedrule2): Deprecated The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). +* [RenamedRule3](pmd_rules_java_sample.html#renamedrule3): Deprecated The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). +* [RenamedRule4](pmd_rules_java_sample.html#renamedrule4): Deprecated The rule has been renamed. Use instead [JumbledIncrementer](pmd_rules_java_sample.html#jumbledincrementer). * [XSSInDocumentation](pmd_rules_java_sample.html#xssindocumentation): <script>alert('XSS at the beginning');</script> HTML tags might appear at various places. ... ## Additional rulesets diff --git a/pmd-doc/src/test/resources/expected/sample.md b/pmd-doc/src/test/resources/expected/sample.md index ff3c6fc81d..c1f20199a4 100644 --- a/pmd-doc/src/test/resources/expected/sample.md +++ b/pmd-doc/src/test/resources/expected/sample.md @@ -5,7 +5,7 @@ permalink: pmd_rules_java_sample.html folder: pmd/rules/java sidebaractiveurl: /pmd_rules_java.html editmepath: ../rulesets/ruledoctest/sample.xml -keywords: Sample, XSSInDocumentation, OverrideBothEqualsAndHashcode, JumbledIncrementer, DeprecatedSample, RenamedRule, MovedRule +keywords: Sample, XSSInDocumentation, OverrideBothEqualsAndHashcode, JumbledIncrementer, DeprecatedSample, RenamedRule1, RenamedRule2, RenamedRule3, RenamedRule4, MovedRule language: Java --- @@ -204,7 +204,7 @@ public class Foo { ``` -## RenamedRule +## RenamedRule1 Deprecated @@ -257,12 +257,235 @@ Avoid jumbled loop incrementers - its usually a mistake, and is confusing even i **Use this rule with the default properties by just referencing it:** ``` xml - + ``` **Use this rule and customize it:** ``` xml - + + + + + + + + + + + + + +``` + +## RenamedRule2 + +Deprecated + +This rule has been renamed. Use instead: [JumbledIncrementer](#jumbledincrementer) + +**Since:** PMD 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**This rule is defined by the following XPath expression:** +``` xpath +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + +**Example(s):** + +``` java +{%raw%}public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +}{%endraw%} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|sampleAdditionalProperty|the value|This is a additional property for tests|no| +|sampleMultiStringProperty|Value1 \| Value2|Test property with multiple strings|yes. Delimiter is '\|'.| +|sampleDeprecatedProperty|test|Deprecated This is a sample deprecated property for tests|no| +|sampleRegexProperty1|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|The property is of type regex|no| +|sampleRegexProperty2|\[a-z\]\*|The property is of type regex|no| +|sampleRegexProperty3|\\s+|The property is of type regex|no| +|sampleRegexProperty4|\_dd\_|The property is of type regex|no| +|sampleRegexProperty5|\[0-9\]{1,3}|The property is of type regex|no| +|sampleRegexProperty6|\\b|The property is of type regex|no| +|sampleRegexProperty7|\\n|The property is of type regex|no| + +**Use this rule with the default properties by just referencing it:** +``` xml + +``` + +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + +``` + +## RenamedRule3 + +Deprecated + +This rule has been renamed. Use instead: [JumbledIncrementer](#jumbledincrementer) + +Deprecated + +**Since:** PMD 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**This rule is defined by the following XPath expression:** +``` xpath +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + +**Example(s):** + +``` java +{%raw%}public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +}{%endraw%} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|sampleAdditionalProperty|the value|This is a additional property for tests|no| +|sampleMultiStringProperty|Value1 \| Value2|Test property with multiple strings|yes. Delimiter is '\|'.| +|sampleDeprecatedProperty|test|Deprecated This is a sample deprecated property for tests|no| +|sampleRegexProperty1|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|The property is of type regex|no| +|sampleRegexProperty2|\[a-z\]\*|The property is of type regex|no| +|sampleRegexProperty3|\\s+|The property is of type regex|no| +|sampleRegexProperty4|\_dd\_|The property is of type regex|no| +|sampleRegexProperty5|\[0-9\]{1,3}|The property is of type regex|no| +|sampleRegexProperty6|\\b|The property is of type regex|no| +|sampleRegexProperty7|\\n|The property is of type regex|no| + +**Use this rule with the default properties by just referencing it:** +``` xml + +``` + +**Use this rule and customize it:** +``` xml + + + + + + + + + + + + + +``` + +## RenamedRule4 + +Deprecated + +This rule has been renamed. Use instead: [JumbledIncrementer](#jumbledincrementer) + +Deprecated + +**Since:** PMD 1.0 + +**Priority:** Medium (3) + +Avoid jumbled loop incrementers - its usually a mistake, and is confusing even if intentional. + +**This rule is defined by the following XPath expression:** +``` xpath +//ForStatement + [ + ForUpdate/StatementExpressionList/StatementExpression/PostfixExpression/PrimaryExpression/PrimaryPrefix/Name/@Image + = + ancestor::ForStatement/ForInit//VariableDeclaratorId/@Image + ] +``` + +**Example(s):** + +``` java +{%raw%}public class JumbledIncrementerRule1 { + public void foo() { + for (int i = 0; i < 10; i++) { // only references 'i' + for (int k = 0; k < 20; i++) { // references both 'i' and 'k' + System.out.println("Hello"); + } + } + } +}{%endraw%} +``` + +**This rule has the following properties:** + +|Name|Default Value|Description|Multivalued| +|----|-------------|-----------|-----------| +|sampleAdditionalProperty|the value|This is a additional property for tests|no| +|sampleMultiStringProperty|Value1 \| Value2|Test property with multiple strings|yes. Delimiter is '\|'.| +|sampleDeprecatedProperty|test|Deprecated This is a sample deprecated property for tests|no| +|sampleRegexProperty1|\\/\\\*\\s+(default\|package)\\s+\\\*\\/|The property is of type regex|no| +|sampleRegexProperty2|\[a-z\]\*|The property is of type regex|no| +|sampleRegexProperty3|\\s+|The property is of type regex|no| +|sampleRegexProperty4|\_dd\_|The property is of type regex|no| +|sampleRegexProperty5|\[0-9\]{1,3}|The property is of type regex|no| +|sampleRegexProperty6|\\b|The property is of type regex|no| +|sampleRegexProperty7|\\n|The property is of type regex|no| + +**Use this rule with the default properties by just referencing it:** +``` xml + +``` + +**Use this rule and customize it:** +``` xml + diff --git a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml index da81d702d1..4037c8ffb8 100644 --- a/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml +++ b/pmd-doc/src/test/resources/rulesets/ruledoctest/sample.xml @@ -216,8 +216,18 @@ RuleTag with full category and without quotes: Use {% rule java/sample/RenamedRu - + - + + + + + + + + + + diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index b2eb1fbba4..6c2bd482ff 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -923,8 +923,6 @@ ASTCompilationUnit CompilationUnit() : // a module (most common case) [ LOOKAHEAD(ModuleDeclLahead()) ModuleDeclaration() ( EmptyDeclaration() )* ] ( TypeDeclaration() ( EmptyDeclaration() )* )* - ( < "\u001a" > )? - ( < "~[]" > )? // what's this for? Do you mean ( < ~[] > )*, i.e. "any character"? { jjtThis.setComments(token_source.comments); diff --git a/pmd-java/pom.xml b/pmd-java/pom.xml index cc59f42d16..bd5a99cdbf 100644 --- a/pmd-java/pom.xml +++ b/pmd-java/pom.xml @@ -242,12 +242,6 @@ annotations test - - io.kotlintest - kotlintest-runner-junit5 - 3.1.8 - test - diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java index 0009521312..6fa413c51a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTAnyTypeDeclaration.java @@ -37,7 +37,8 @@ public interface ASTAnyTypeDeclaration TypeParamOwnerNode, ASTBodyDeclaration, ASTTopLevelDeclaration, - FinalizableNode { + FinalizableNode, + JavadocCommentOwner { @Override @NonNull diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTConstructorDeclaration.java index 2f621e353a..69c74eaa08 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTConstructorDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTConstructorDeclaration.java @@ -5,7 +5,9 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol; /** @@ -34,6 +36,10 @@ public final class ASTConstructorDeclaration extends AbstractMethodOrConstructor return getImage(); } + @Override + protected @Nullable JavaccToken getPreferredReportLocation() { + return getModifiers().getLastToken().getNext(); + } @Override protected R acceptVisitor(JavaVisitor visitor, P data) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java index 14aba1721d..f95b7d8002 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTEnumConstant.java @@ -22,7 +22,8 @@ public final class ASTEnumConstant extends AbstractJavaTypeNode InvocationNode, AccessNode, ASTBodyDeclaration, - InternalInterfaces.VariableIdOwner { + InternalInterfaces.VariableIdOwner, + JavadocCommentOwner { private OverloadSelectionResult result; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java index 813dd84ed7..ba2d8d8f67 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclaration.java @@ -4,7 +4,10 @@ package net.sourceforge.pmd.lang.java.ast; +import org.checkerframework.checker.nullness.qual.Nullable; + import net.sourceforge.pmd.lang.ast.SignedNode; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.multifile.signature.JavaFieldSignature; import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; @@ -28,7 +31,8 @@ public final class ASTFieldDeclaration extends AbstractJavaNode LeftRecursiveNode, AccessNode, ASTBodyDeclaration, - InternalInterfaces.MultiVariableIdOwner { + InternalInterfaces.MultiVariableIdOwner, + JavadocCommentOwner { private JavaFieldSignature signature; @@ -36,6 +40,11 @@ public final class ASTFieldDeclaration extends AbstractJavaNode super(id); } + @Override + protected @Nullable JavaccToken getPreferredReportLocation() { + // report on the identifier and not the annotations + return getVarIds().firstOrThrow().getFirstToken(); + } @Override protected R acceptVisitor(JavaVisitor visitor, P data) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.java index 79f207d9ff..3c88a6d878 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclaration.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol; import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; @@ -50,6 +51,11 @@ public final class ASTMethodDeclaration extends AbstractMethodOrConstructorDecla } + @Override + protected @Nullable JavaccToken getPreferredReportLocation() { + return TokenUtils.nthPrevious(getModifiers().getLastToken(), getFormalParameters().getFirstToken(), 1); + } + /** * Returns the simple name of the method. * diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java index a5d13115f6..8718b947b5 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTMethodOrConstructorDeclaration.java @@ -35,7 +35,8 @@ public interface ASTMethodOrConstructorDeclaration SignedNode, ASTBodyDeclaration, TypeParamOwnerNode, - GenericNode { + GenericNode, + JavadocCommentOwner { @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java index f2e1d4fba2..9fdaafd354 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java @@ -17,7 +17,7 @@ package net.sourceforge.pmd.lang.java.ast; * * */ -public final class ASTPackageDeclaration extends AbstractJavaNode implements Annotatable, ASTTopLevelDeclaration { +public final class ASTPackageDeclaration extends AbstractJavaNode implements Annotatable, ASTTopLevelDeclaration, JavadocCommentOwner { ASTPackageDeclaration(int id) { super(id); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java index 5e0e0de235..5fc9c4dcdf 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractAnyTypeDeclaration.java @@ -7,6 +7,7 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.types.JClassType; import net.sourceforge.pmd.lang.rule.xpath.DeprecatedAttribute; @@ -24,6 +25,12 @@ abstract class AbstractAnyTypeDeclaration extends AbstractTypedSymbolDeclarator< super(i); } + @Override + protected @Nullable JavaccToken getPreferredReportLocation() { + return isAnonymous() ? null + : getModifiers().getLastToken().getNext(); + } + /** * @deprecated Use {@link #getSimpleName()} */ diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaExpr.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaExpr.java index a4235602d6..1216ee5e2c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaExpr.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaExpr.java @@ -30,6 +30,7 @@ abstract class AbstractJavaExpr extends AbstractJavaTypeNode implements ASTExpre @Override public @Nullable Object getConstValue() { if (constValue == NOT_COMPUTED) { // NOPMD we want identity semantics + constValue = null; // remove the sentinel, so that we don't reenter on cycle constValue = buildConstValue(); } return constValue; diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java index 2a81aaf73b..d4b60ac96f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/AbstractJavaNode.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.java.ast; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.AstVisitor; import net.sourceforge.pmd.lang.ast.impl.javacc.AbstractJjtreeNode; @@ -23,6 +24,15 @@ abstract class AbstractJavaNode extends AbstractJjtreeNode { return token.getReportLocation(); } + /** + * @deprecated Use {@link #getText()} + */ @Override + @Deprecated public String getImage() { - return token.getImage(); + return super.getImage(); + } + + public final JavaccToken getToken() { + return super.getFirstToken(); } /** @@ -67,7 +75,7 @@ public abstract class Comment extends AbstractJjtreeNode { * @return List of lines of the comments */ private List multiLinesIn() { - String[] lines = NEWLINES_PATTERN.split(getImage()); + String[] lines = NEWLINES_PATTERN.split(getText()); List filteredLines = new ArrayList<>(lines.length); for (String rawLine : lines) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentPass.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentPass.java new file mode 100644 index 0000000000..f1aa1b33e0 --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentPass.java @@ -0,0 +1,62 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import java.util.Collections; +import java.util.List; + +import org.checkerframework.checker.nullness.qual.Nullable; + +import net.sourceforge.pmd.lang.ast.GenericToken; +import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; +import net.sourceforge.pmd.util.DataMap; +import net.sourceforge.pmd.util.DataMap.SimpleDataKey; + +final class CommentAssignmentPass { + + private static final SimpleDataKey FORMAL_COMMENT_KEY = DataMap.simpleDataKey("java.comment"); + + private CommentAssignmentPass() { + // utility class + } + + static @Nullable FormalComment getComment(JavadocCommentOwner commentOwner) { + return commentOwner.getUserMap().get(CommentAssignmentPass.FORMAL_COMMENT_KEY); + } + + private static void setComment(JavadocCommentOwner commentableNode, FormalComment comment) { + commentableNode.getUserMap().set(FORMAL_COMMENT_KEY, comment); + } + + public static void assignCommentsToDeclarations(ASTCompilationUnit root) { + final List comments = root.getComments(); + if (comments.isEmpty()) { + return; + } + + outer: + for (JavadocCommentOwner commentableNode : javadocOwners(root)) { + JavaccToken firstToken = commentableNode.getFirstToken(); + + for (JavaccToken maybeComment : GenericToken.previousSpecials(firstToken)) { + if (maybeComment.kind == JavaTokenKinds.FORMAL_COMMENT) { + FormalComment comment = new FormalComment(maybeComment); + // deduplicate the comment + int idx = Collections.binarySearch(comments, comment, Comment::compareLocation); + assert idx >= 0 : "Formal comment not found? " + comment; + comment = (FormalComment) comments.get(idx); + + setComment(commentableNode, comment); + continue outer; + } + } + } + } + + private static NodeStream javadocOwners(ASTCompilationUnit root) { + return root.descendants().crossFindBoundaries().filterIs(JavadocCommentOwner.class); + } +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentUtil.java deleted file mode 100644 index 9275189e60..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/CommentUtil.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.ast; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; - -import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; -import net.sourceforge.pmd.lang.java.javadoc.JavadocTag; - -/** - * - * @deprecated This utility class is deprecated and will be removed with PMD 7.0.0. - * Its methods have been intended to parse javadoc tags. - * A more useful solution will be added around the AST node {@link FormalComment}, - * which contains as children {@link JavadocElement} nodes, which in - * turn provide access to the {@link JavadocTag}. - */ -@Deprecated // will be remove with PMD 7.0.0 -public final class CommentUtil { - - private static final Pattern JAVADOC_TAG = Pattern.compile("@[A-Za-z0-9]+"); - - private CommentUtil() { - } - - /** - * Gets the next word (characters until next whitespace, punctuation, - * or anything that is not a letter or digit) at the given position. - * - * @param text the complete text - * @param position the position, at which the word starts - * @return the word - * - * @deprecated This method is deprecated and will be removed with PMD 7.0.0. - * This method has been intended to parse javadoc tags. - * A more useful solution will be added around the AST node {@link FormalComment}, - * which contains as children {@link JavadocElement} nodes, which in - * turn provide access to the {@link JavadocTag}. - */ - @Deprecated // will be removed with PMD 7.0.0 - public static String wordAfter(String text, int position) { - if (text == null || position >= text.length()) { - return null; - } - int newposition = position + 1; - int end = newposition; - char ch = text.charAt(end); - - while (Character.isLetterOrDigit(ch) && end < text.length()) { - ch = text.charAt(++end); - } - - return text.substring(newposition, end); - } - - /** - * Gets the remaining line after a specific position. - * - * @param text the complete text - * @param position the position from which the comment should be returned - * @return the part of the text - * - * @deprecated This method is deprecated and will be removed with PMD 7.0.0. - * This method has been intended to parse javadoc tags. - * A more useful solution will be added around the AST node {@link FormalComment}, - * which contains as children {@link JavadocElement} nodes, which in - * turn provide access to the {@link JavadocTag}. - */ - @Deprecated // will be removed with PMD 7.0.0 - public static String javadocContentAfter(String text, int position) { - if (text == null || position > text.length()) { - return null; - } - - int endPos = text.indexOf('\n', position); - if (endPos < 0) { - endPos = text.length(); - } - - if (StringUtils.isNotBlank(text.substring(position, endPos))) { - return text.substring(position, endPos).trim(); - } - - if (text.indexOf('@', endPos) >= 0) { - return null; // nope, this is another entry - } - - // try next line - int nextEndPos = text.indexOf('\n', endPos + 1); - - if (StringUtils.isNotBlank(text.substring(endPos, nextEndPos))) { - return text.substring(endPos, nextEndPos).trim(); - } - - return null; - } - - /** - * Finds all the javadoc tags in the (formal) comment. - * Returns a map from javadoc tag to index position. - * - *

    Note: If a tag is used multiple times, the last occurrence is returned. - * - * @param comment the raw comment - * @return mapping of javadoc tag to index position - * - * @deprecated This method is deprecated and will be removed with PMD 7.0.0. - * This method has been intended to parse javadoc tags. - * A more useful solution will be added around the AST node {@link FormalComment}, - * which contains as children {@link JavadocElement} nodes, which in - * turn provide access to the {@link JavadocTag}. - */ - @Deprecated // will be removed with PMD 7.0.0 - public static Map javadocTagsIn(String comment) { - Map tags = new HashMap<>(); - - if (comment != null) { - Matcher m = JAVADOC_TAG.matcher(comment); - while (m.find()) { - String match = comment.substring(m.start() + 1, m.end()); - tags.put(match, m.start()); - } - } - - return tags; - } - - /** - * Removes the leading comment marker (like {@code *}) of each line - * of the comment as well as the start marker ({@code //}, {@code /*} or {@code /**} - * and the end markers (*/). - * - * @param comment the raw comment - * @return List of lines of the comments - * - * @deprecated This method will be removed with PMD 7.0.0. - * It has been replaced by {@link Comment#getFilteredComment()}. - */ - @Deprecated // will be removed with PMD 7.0.0 - public static List multiLinesIn(String comment) { - // temporary createa a Multiline Comment Node - JavaccToken t = new JavaccToken(comment); - MultiLineComment node = new MultiLineComment(t); - return Arrays.asList(Comment.NEWLINES_PATTERN.split(node.getFilteredComment())); - } - - /** - * Similar to the String.trim() function, this one removes the leading and - * trailing empty/blank lines from the line list. - * - * @param lines the list of lines, which might contain empty lines - * @return the lines without leading or trailing blank lines. - * - * @deprecated This method will be removed with PMD 7.0.0. - * It is not needed anymore, since {@link Comment#getFilteredComment()} - * returns already the filtered and trimmed comment text. - */ - @Deprecated // will be removed with PMD 7.0.0 - public static List trim(List lines) { - return Comment.trim(lines); - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/FormalComment.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/FormalComment.java index 4f47dd5bbf..9b5bb59c79 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/FormalComment.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/FormalComment.java @@ -18,7 +18,8 @@ public class FormalComment extends Comment { public FormalComment(JavaccToken t) { super(t); - findJavadocs(t); + assert t.kind == JavaTokenKinds.FORMAL_COMMENT; + findJavadocs(); } @Override @@ -26,7 +27,7 @@ public class FormalComment extends Comment { return "FormalComment"; } - private void findJavadocs(JavaccToken t) { + private void findJavadocs() { List kids = new ArrayList<>(); Matcher javadocTagMatcher = JAVADOC_TAG.matcher(getFilteredComment()); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/InternalApiBridge.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/InternalApiBridge.java index d7706dae6c..b9ecb36ee4 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/InternalApiBridge.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/InternalApiBridge.java @@ -8,6 +8,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccTokenDocument; import net.sourceforge.pmd.lang.java.internal.JavaAstProcessor; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; @@ -177,6 +178,14 @@ public final class InternalApiBridge { ((AbstractAnyTypeDeclaration) declaration).setBinaryName(binaryName, canon); } + public static void assignComments(ASTCompilationUnit root) { + CommentAssignmentPass.assignCommentsToDeclarations(root); + } + + public static @Nullable JavaccToken getReportLocation(JavaNode node) { + return ((AbstractJavaNode) node).getPreferredReportLocation(); + } + public static JavaccTokenDocument.TokenDocumentBehavior javaTokenDoc() { return JavaTokenDocument.INSTANCE; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavadocCommentOwner.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavadocCommentOwner.java new file mode 100644 index 0000000000..32d32af77e --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/JavadocCommentOwner.java @@ -0,0 +1,23 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * A node that may own a javadoc comment. + */ +public interface JavadocCommentOwner extends JavaNode { + // TODO can record components be documented individually? + + /** + * Returns the javadoc comment that applies to this declaration. If + * there is none, returns null. + */ + default @Nullable FormalComment getJavadocComment() { + return CommentAssignmentPass.getComment(this); + } + +} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java index 427205a6f3..7369d74022 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaAstProcessor.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.lang.java.internal; -import java.text.MessageFormat; import java.util.IdentityHashMap; import java.util.Map; import java.util.function.Supplier; @@ -16,16 +15,15 @@ import net.sourceforge.pmd.benchmark.TimedOperation; import net.sourceforge.pmd.benchmark.TimedOperationCategory; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; -import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.java.symbols.SymbolResolver; import net.sourceforge.pmd.lang.java.symbols.internal.UnresolvedClassStore; import net.sourceforge.pmd.lang.java.symbols.internal.ast.SymbolResolutionPass; import net.sourceforge.pmd.lang.java.symbols.table.internal.ReferenceCtx; -import net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger; import net.sourceforge.pmd.lang.java.symbols.table.internal.SymbolTableResolver; import net.sourceforge.pmd.lang.java.types.TypeSystem; import net.sourceforge.pmd.lang.java.types.internal.infer.TypeInferenceLogger; @@ -60,7 +58,7 @@ public final class JavaAstProcessor { private final TypeInferenceLogger typeInferenceLogger; - private final SemanticChecksLogger logger; + private final SemanticErrorReporter logger; private final LanguageVersion languageVersion; private final TypeSystem typeSystem; @@ -71,7 +69,7 @@ public final class JavaAstProcessor { private JavaAstProcessor(TypeSystem typeSystem, SymbolResolver symResolver, - SemanticChecksLogger logger, + SemanticErrorReporter logger, TypeInferenceLogger typeInfLogger, LanguageVersion languageVersion) { @@ -94,6 +92,13 @@ public final class JavaAstProcessor { } } + + public JClassSymbol findSymbolCannotFail(String name) { + JClassSymbol found = getSymResolver().resolveClassFromCanonicalName(name); + return found == null ? makeUnresolvedReference(name, 0) + : found; + } + public JClassSymbol makeUnresolvedReference(String canonicalName, int typeArity) { return unresolvedTypes.makeUnresolvedReference(canonicalName, typeArity); } @@ -109,7 +114,7 @@ public final class JavaAstProcessor { return symResolver; } - public SemanticChecksLogger getLogger() { + public SemanticErrorReporter getLogger() { return logger; } @@ -135,34 +140,21 @@ public final class JavaAstProcessor { bench("2. Symbol table resolution", () -> SymbolTableResolver.traverse(this, acu)); bench("3. AST disambiguation", () -> InternalApiBridge.disambigWithCtx(NodeStream.of(acu), ReferenceCtx.root(this, acu))); + bench("4. Comment assignment", () -> InternalApiBridge.assignComments(acu)); } public TypeSystem getTypeSystem() { return typeSystem; } - public static SemanticChecksLogger defaultLogger() { - return new SemanticChecksLogger() { - private String locPrefix(JavaNode loc) { - return "[" + loc.getBeginLine() + "," + loc.getBeginColumn() + "] "; - } - - @Override - public void warning(JavaNode location, String message, Object... args) { - DEFAULT_LOG.fine(() -> locPrefix(location) + MessageFormat.format(message, args)); - } - - @Override - public void error(JavaNode location, String message, Object... args) { - DEFAULT_LOG.severe(() -> locPrefix(location) + MessageFormat.format(message, args)); - } - }; + public static SemanticErrorReporter defaultLogger() { + return SemanticErrorReporter.reportToLogger(DEFAULT_LOG); } public static JavaAstProcessor create(SymbolResolver symResolver, TypeSystem typeSystem, LanguageVersion languageVersion, - SemanticChecksLogger logger) { + SemanticErrorReporter logger) { return new JavaAstProcessor( typeSystem, @@ -175,7 +167,7 @@ public final class JavaAstProcessor { public static JavaAstProcessor create(ClassLoader classLoader, LanguageVersion languageVersion, - SemanticChecksLogger logger, + SemanticErrorReporter logger, TypeInferenceLogger typeInfLogger) { TypeSystem typeSystem = TYPE_SYSTEMS.computeIfAbsent(classLoader, TypeSystem::new); @@ -190,7 +182,7 @@ public final class JavaAstProcessor { public static JavaAstProcessor create(TypeSystem typeSystem, LanguageVersion languageVersion, - SemanticChecksLogger semanticLogger, + SemanticErrorReporter semanticLogger, TypeInferenceLogger typeInfLogger) { return new JavaAstProcessor( typeSystem, diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java index 6677e0da3c..60f400864c 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolation.java @@ -13,6 +13,7 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; @@ -22,6 +23,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; import net.sourceforge.pmd.lang.java.ast.AccessNode; +import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; @@ -40,16 +42,23 @@ import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; @Deprecated public class JavaRuleViolation extends ParametricRuleViolation { - public JavaRuleViolation(Rule rule, @NonNull JavaNode node, String filename, String message) { - super(rule, filename, node, message); + public JavaRuleViolation(Rule rule, @NonNull JavaNode node, String message) { + super(rule, node, message); ASTCompilationUnit root = node.getRoot(); packageName = root.getPackageName(); - className = getClassName(node); methodName = getMethodName(node); variableName = getVariableNameIfExists(node); + + JavaccToken preferredLoc = InternalApiBridge.getReportLocation(node); + if (preferredLoc != null) { + beginLine = preferredLoc.getBeginLine(); + beginColumn = preferredLoc.getBeginColumn(); + endLine = preferredLoc.getEndLine(); + endColumn = preferredLoc.getEndColumn(); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java index 465d9c781e..2ba5f6ff58 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideRule.java @@ -4,30 +4,29 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; -import java.util.List; +import java.util.LinkedHashSet; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; -import java.util.Stack; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.stream.Collector; -import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant; -import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; -import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; +import org.checkerframework.checker.nullness.qual.NonNull; + +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; +import net.sourceforge.pmd.lang.java.ast.JModifier; +import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.internal.PrettyPrintingUtil; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; +import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol; +import net.sourceforge.pmd.lang.java.symbols.table.internal.SuperTypesEnumerator; +import net.sourceforge.pmd.lang.java.types.JMethodSig; +import net.sourceforge.pmd.lang.java.types.TypeOps; +import net.sourceforge.pmd.lang.rule.RuleTargetSelector; /** @@ -38,343 +37,123 @@ import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; */ public class MissingOverrideRule extends AbstractJavaRule { - private static final Logger LOG = Logger.getLogger(MissingOverrideRule.class.getName()); - private final Stack currentLookup = new Stack<>(); - @Override - public Object visit(ASTCompilationUnit node, Object data) { - currentLookup.clear(); - return super.visit(node, data); + protected @NonNull RuleTargetSelector buildTargetSelector() { + return RuleTargetSelector.forTypes(ASTAnyTypeDeclaration.class); } - @Override - public Object visit(ASTClassOrInterfaceDeclaration node, Object data) { - currentLookup.push(getMethodLookup(node.getType())); - super.visit(node, data); - currentLookup.pop(); - + public Object visitJavaNode(JavaNode node, Object data) { + visitTypeDecl((ASTAnyTypeDeclaration) node, (RuleContext) data); return data; } - @Override - public Object visit(ASTEnumDeclaration node, Object data) { - currentLookup.push(getMethodLookup(node.getType())); - super.visit(node, data); - currentLookup.pop(); + private void visitTypeDecl(ASTAnyTypeDeclaration node, RuleContext data) { + // collect methods that may be violations, ie: + // - may override another method (non private, non static) + // - not already annotated @Override - return data; - } + RelevantMethodSet relevantMethods = new RelevantMethodSet(node.getSymbol()); - - - @Override - public Object visit(ASTAllocationExpression node, Object data) { - if (node.isAnonymousClass()) { - currentLookup.push(getMethodLookup(node.getType())); - } - super.visit(node, data); - - if (node.isAnonymousClass()) { - currentLookup.pop(); + for (ASTMethodDeclaration methodDecl : node.getDeclarations().filterIs(ASTMethodDeclaration.class)) { + relevantMethods.addIfRelevant(methodDecl); } - return data; + if (relevantMethods.tracked.isEmpty()) { + return; + } + + Set violatingMethods = + // stream all methods of supertypes + SuperTypesEnumerator.ALL_STRICT_SUPERTYPES + .stream(node.getTypeMirror()) + // Filter down to those that may be overridden by one of the possible violations + // This considers name, arity, and accessibility + // vvvvvvvvvvvvvvvvvvvvvvvvvvv + .flatMap(st -> st.streamDeclaredMethods(relevantMethods::isRelevant)) + // For those methods, a simple override-equivalence check is enough, + // because we already know they're accessible, and declared in a supertype + .collect(relevantMethods.overriddenRelevantMethodsCollector()); + + for (ASTMethodDeclaration violatingMethod : violatingMethods) { + addViolation(data, violatingMethod, new Object[] { PrettyPrintingUtil.displaySignature(violatingMethod) }); + } } - - @Override - public Object visit(ASTEnumConstant node, Object data) { - // FIXME, ASTEnumConstant needs typeres support! - // if (node.isAnonymousClass()) { - // currentExploredClass.push(node.getType()); - // } - super.visit(node, data); - - // if (node.isAnonymousClass()) { - // currentExploredClass.pop(); - // } - - return data; - } - - /** - * Returns a map of method name to methods with the same name (overloads). - * The map contains a MethodWrapper for all methods declared in this class. - * - * @param exploredType Type to explore + * This does a prefilter, so that we only collect methods of supertypes + * that may be overridden by a sub method. For a method to be potentially + * a super method, it must have same arity */ - private MethodLookup getMethodLookup(Class exploredType) { - if (exploredType == null) { - return null; - } + private static final class RelevantMethodSet { - try { - Set overridden = overriddenMethods(exploredType); - Map>> result = new HashMap<>(); + // name to considered arities + private final Map map = new HashMap<>(); + // nodes that may be violations + private final Set tracked = new LinkedHashSet<>(); - for (Method m : exploredType.getDeclaredMethods()) { - if (!result.containsKey(m.getName())) { - result.put(m.getName(), new HashMap>()); - } + private final JClassSymbol site; - Map> pCountToOverloads = result.get(m.getName()); - - int paramCount = m.getParameterTypes().length; - if (!pCountToOverloads.containsKey(paramCount)) { - pCountToOverloads.put(paramCount, new ArrayList()); - } - - pCountToOverloads.get(paramCount).add(m); - } - - return new MethodLookup(result, overridden); - } catch (final LinkageError e) { - // This is an incomplete classpath, report the missing class - LOG.log(Level.FINE, "Possible incomplete auxclasspath: Error while processing methods", e); - return null; - } - } - - - /** - * Returns the set of methods declared in this type that are overridden. - * - * @param exploredType The type to explore - */ - private Set overriddenMethods(Class exploredType) { - return overriddenMethodsRec(exploredType, true, new HashSet<>(Arrays.asList(exploredType.getDeclaredMethods())), new HashSet(), new HashSet>(), false); - } - - - private Set overriddenMethodsRec(Class exploredType, boolean skip, Set candidates, Set result, Set> alreadyExplored, boolean onlyPublic) { - - if (candidates.isEmpty() || alreadyExplored.contains(exploredType)) { - return result; - } - - alreadyExplored.add(exploredType); - - if (!skip) { - Set toRemove = new HashSet<>(); - for (Method dm : exploredType.getDeclaredMethods()) { - if (onlyPublic && !Modifier.isPublic(dm.getModifiers()) - || Modifier.isPrivate(dm.getModifiers()) - || Modifier.isStatic(dm.getModifiers())) { - continue; - } - - for (Method cand : candidates) { - if (Modifier.isPrivate(dm.getModifiers()) || Modifier.isStatic(dm.getModifiers())) { - continue; - } - - if (cand.getName().equals(dm.getName()) && Arrays.equals(cand.getParameterTypes(), dm.getParameterTypes())) { - // cand is overridden - result.add(cand); - toRemove.add(cand); - // Several methods are eligible, because of return type covariance - // We could do away with adding only the first one to the result, - // but then the other would stay in the candidates and we'd explore - // the rest of the tree unnecessarily - } - } - candidates.removeAll(toRemove); // no need to look for it elsewhere - } - } - - if (candidates.isEmpty()) { - return result; - } - - Class superClass = exploredType.getSuperclass(); - if (superClass != null) { - overriddenMethodsRec(superClass, false, candidates, result, alreadyExplored, false); - } - - for (Class iface : exploredType.getInterfaces()) { - overriddenMethodsRec(iface, false, candidates, result, alreadyExplored, false); - } - - if (exploredType.isInterface() && exploredType.getInterfaces().length == 0) { - // implicit public object member declarations - if (!alreadyExplored.contains(Object.class)) { - overriddenMethodsRec(Object.class, false, candidates, result, alreadyExplored, true); - } - } - - return result; - } - - - @Override - public Object visit(ASTMethodDeclaration node, Object data) { - if (currentLookup.isEmpty() || currentLookup.peek() == null) { - return super.visit(node, data); - } - - if (node.isAnnotationPresent(Override.class)) { - // we assume the compiler has already checked it, so it's correct - return super.visit(node, data); - } - - try { - boolean overridden = currentLookup.peek().isOverridden(node.getName(), node.getFormalParameters()); - if (overridden) { - addViolation(data, node, new Object[]{PrettyPrintingUtil.displaySignature(node)}); - } - } catch (NoSuchMethodException e) { - // may happen in the body of an enum constant, - // because the method lookup used is the one of - // the parent class. - LOG.fine("MissingOverride encountered unexpected method " + node.getName()); - // throw new RuntimeException(e); // uncomment when enum constants are handled by typeres - } - return super.visit(node, data); - } - - - - private static class MethodLookup { - - // method name, parameter count, methods - private final Map>> map; - private final Set overridden; - - - private MethodLookup(Map>> map, Set overridden) { - this.map = map; - this.overridden = overridden; - - for (Map> overloadSet : map.values()) { - for (Entry> sameParamCountMethods : overloadSet.entrySet()) { - // bridges have the same name and param count as the bridged method - resolveBridges(sameParamCountMethods.getValue()); - } - } + private RelevantMethodSet(JClassSymbol site) { + this.site = site; } - private void resolveBridges(List overloads) { - if (overloads.size() <= 1) { + // add a method if it may be a violation + // this builds the data structure for isRelevant to work + void addIfRelevant(ASTMethodDeclaration m) { + if (m.isAnnotationPresent(Override.class) + || m.getModifiers().hasAny(JModifier.STATIC, JModifier.PRIVATE)) { return; } - - // partition the overloads - List bridges = new ArrayList<>(); - List notBridges = new ArrayList<>(); - - for (Method m : overloads) { - if (m.isBridge()) { - bridges.add(m); - } else { - notBridges.add(m); - } - } - - if (bridges.isEmpty()) { - return; - } - - // each bridge necessarily calls another non-bridge method, which is overridden - - if (notBridges.size() == bridges.size()) { - // This is a good heuristic, though not perfect. - - // Most of the time, bridges is one-to-one to notBridges, and we can safely assume that - // all non-bridge methods are overridden, since they need a bridge method - - // This chokes on overloads which don't override a previous definition, in which case there's no - // generated bridge for that overload. Short of statically analysing type parameters, or reading - // the bytecode to find the delegation call, we have no way to find out which of the overloads is - // overridden. An example of that is in RuleViolationComparator: there's one bridge - // compare(Object, Object) for the overload compare(RV, RV), but we can't know because there's - // another overload, compare(String, String) which is equally eligible - - // It's also possible that several bridges are generated for the same method, when the method - // was already redefined several times with a different bound. An example of that is in - // PropertyDescriptorConversionWrapper.SingleValue.Packaged and similar subclasses: each of the - // levels of the hierarchy redefine the original method with a tighter bound on the type parameter. - // Three bridges are generated for populate() on concrete builder classes. - - // The two situations could happen together, and if they balance out, that gives a false positive - // with the current test (size are equal). If they don't balance out, then we don't report anything, - // which is why this test seems the safest. - - // Depending on the real-world frequency of those two situations happening together, we may rather - // use notBridges.size() <= bridges.size(), to remove FNs caused by additional bridges. - - overridden.addAll(notBridges); - } - - overloads.removeAll(bridges); // better prune the candidate overloads anyway + // then add it + BitSet aritySet = map.computeIfAbsent(m.getName(), n -> new BitSet(m.getArity() + 1)); + aritySet.set(m.getArity()); + tracked.add(m); } - - - - - private List getMethods(String name, int paramCount) throws NoSuchMethodException { - Map> overloads = map.get(name); - if (overloads == null) { - throw new NoSuchMethodException(name); - } - - List methods = overloads.get(paramCount); - if (methods == null || methods.isEmpty()) { - throw new NoSuchMethodException(name); - } - return methods; - } - - /** - * Tries to determine if the method with the given name and parameter count is overridden - * - * @return True or false - * - * @throws NoSuchMethodException if no method is registered with this name and paramcount, which is a bug - */ - boolean isOverridden(String name, ASTFormalParameters params) throws NoSuchMethodException { - List methods = getMethods(name, params.size()); - - if (methods.size() == 1) { // only one method with this name and parameter count, we can conclude - return overridden.contains(methods.get(0)); - } else { // several overloads with same name and count, cannot be determined without comparing parameters - Class[] paramTypes = getParameterTypes(params); - if (paramTypes == null) { - return false; - } - for (Method m : methods) { - if (Arrays.equals(m.getParameterTypes(), paramTypes)) { - // we found our overload - return overridden.contains(m); - } - } + // we use this to only consider methods that may produce a violation, + // among the supertype methods + boolean isRelevant(JMethodSymbol superMethod) { + if (!TypeOps.isOverridableIn(superMethod, site)) { return false; } + BitSet aritySet = map.get(superMethod.getSimpleName()); + return aritySet != null && aritySet.get(superMethod.getArity()); } - - private static Class[] getParameterTypes(ASTFormalParameters params) { - Class[] paramTypes = new Class[params.size()]; - int i = 0; - for (ASTFormalParameter p : params) { - Class pType = p.getType(); - if (pType == null) { - // fail, couldn't resolve one parameter - return null; + // then, if the superSig, which comes from a supertype, is overridden + // by a relevant method (ie a method that is a violation), then that + // node truly is a violation, and is added to the output set. + void addToSetIfIsOverridden(Set relevantOverridingMethods, + JMethodSig superSig) { + ASTMethodDeclaration subSig = null; + for (ASTMethodDeclaration it : tracked) { + if (TypeOps.areOverrideEquivalent(it.getGenericSignature(), superSig)) { + subSig = it; + // we assume there is a single relevant method that may match, + // otherwise it would be a compile-time error + break; } - - paramTypes[i++] = pType; } - return paramTypes; + if (subSig != null) { + relevantOverridingMethods.add(subSig); + tracked.remove(subSig); // speedup the check for later + } } + Collector> overriddenRelevantMethodsCollector() { + return Collector.of( + HashSet::new, + this::addToSetIfIsOverridden, + (map1, map2) -> { + throw new UnsupportedOperationException("Dont use a parallel stream"); + }, + set -> set + ); + } } - - } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentRule.java index b4d5609beb..ea84392193 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentRule.java @@ -5,8 +5,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; -import static net.sourceforge.pmd.lang.java.rule.codestyle.ConfusingTernaryRule.unwrapParentheses; - import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -14,7 +12,6 @@ import java.util.Comparator; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -24,24 +21,25 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.NodeStream; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr; +import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.AccessType; import net.sourceforge.pmd.lang.java.ast.ASTAssignmentExpression; import net.sourceforge.pmd.lang.java.ast.ASTBlock; import net.sourceforge.pmd.lang.java.ast.ASTBodyDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement; import net.sourceforge.pmd.lang.java.ast.ASTCatchClause; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; +import net.sourceforge.pmd.lang.java.ast.ASTCatchParameter; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalAndExpression; import net.sourceforge.pmd.lang.java.ast.ASTConditionalExpression; -import net.sourceforge.pmd.lang.java.ast.ASTConditionalOrExpression; +import net.sourceforge.pmd.lang.java.ast.ASTConstructorCall; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTContinueStatement; import net.sourceforge.pmd.lang.java.ast.ASTDoStatement; -import net.sourceforge.pmd.lang.java.ast.ASTEnumBody; import net.sourceforge.pmd.lang.java.ast.ASTExpression; import net.sourceforge.pmd.lang.java.ast.ASTExpressionStatement; +import net.sourceforge.pmd.lang.java.ast.ASTFieldAccess; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFinallyClause; import net.sourceforge.pmd.lang.java.ast.ASTForInit; @@ -50,15 +48,14 @@ import net.sourceforge.pmd.lang.java.ast.ASTForUpdate; import net.sourceforge.pmd.lang.java.ast.ASTForeachStatement; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter; import net.sourceforge.pmd.lang.java.ast.ASTIfStatement; +import net.sourceforge.pmd.lang.java.ast.ASTInfixExpression; import net.sourceforge.pmd.lang.java.ast.ASTInitializer; import net.sourceforge.pmd.lang.java.ast.ASTLabeledStatement; import net.sourceforge.pmd.lang.java.ast.ASTLambdaExpression; import net.sourceforge.pmd.lang.java.ast.ASTLocalVariableDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTLoopStatement; +import net.sourceforge.pmd.lang.java.ast.ASTMethodCall; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTName; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression; -import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; -import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTResourceList; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; import net.sourceforge.pmd.lang.java.ast.ASTStatement; @@ -66,21 +63,26 @@ import net.sourceforge.pmd.lang.java.ast.ASTSwitchArrowBranch; import net.sourceforge.pmd.lang.java.ast.ASTSwitchExpression; import net.sourceforge.pmd.lang.java.ast.ASTSwitchLabel; import net.sourceforge.pmd.lang.java.ast.ASTSwitchStatement; +import net.sourceforge.pmd.lang.java.ast.ASTThisExpression; import net.sourceforge.pmd.lang.java.ast.ASTThrowStatement; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; -import net.sourceforge.pmd.lang.java.ast.ASTTypeBody; import net.sourceforge.pmd.lang.java.ast.ASTUnaryExpression; +import net.sourceforge.pmd.lang.java.ast.ASTVariableAccess; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; -import net.sourceforge.pmd.lang.java.ast.ASTVariableInitializer; import net.sourceforge.pmd.lang.java.ast.ASTWhileStatement; import net.sourceforge.pmd.lang.java.ast.ASTYieldStatement; +import net.sourceforge.pmd.lang.java.ast.BinaryOp; +import net.sourceforge.pmd.lang.java.ast.InvocationNode; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.JavaVisitorBase; +import net.sourceforge.pmd.lang.java.ast.QualifiableExpression; +import net.sourceforge.pmd.lang.java.ast.UnaryOp; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.lang.java.symboltable.ClassScope; -import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration; -import net.sourceforge.pmd.lang.symboltable.Scope; +import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol; +import net.sourceforge.pmd.lang.java.symbols.JLocalVariableSymbol; +import net.sourceforge.pmd.lang.java.symbols.JVariableSymbol; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -106,6 +108,17 @@ public class UnusedAssignmentRule extends AbstractJavaRule { or at least proper graph algorithms like toposort) -> this is pretty invisible as it causes false negatives, not FPs * test ternary expr + * more precise exception handling: since we have access to + the overload for method & ctors, we can know where its thrown + exceptions may end up in enclosing catches. + * extract the reaching definition analysis, to exploit control + flow information in rules + symbol table. The following are needed + to implement scoping of pattern variables, and are already computed + by this analysis: + * whether a switch may fall through + * whether a statement always completes abruptly + * whether a statement never completes abruptly because of break + DONE * conditionals @@ -167,7 +180,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { unused.removeAll(result.usedAssignments); for (AssignmentEntry entry : unused) { - if (isIgnorablePrefixIncrement(entry.rhs)) { + if (entry.isUnaryReassign() && isIgnorablePrefixIncrement(entry.rhs)) { continue; } @@ -176,7 +189,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { if (killers == null || killers.isEmpty()) { // var went out of scope before being used (no assignment kills it, yet it's unused) - if (entry.var.isField()) { + if (entry.var instanceof JFieldSymbol) { // assignments to fields don't really go out of scope continue; } else if (suppressUnusedVariableRuleOverlap(entry)) { @@ -202,13 +215,13 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } else { reason = joinLines("overwritten on lines ", killers); } - if (reason == null && hasExplicitIgnorableName(entry.var.getName())) { + if (reason == null && hasExplicitIgnorableName(entry.var.getSimpleName())) { // Then the variable is never used (cf UnusedVariable) // We ignore those that start with "ignored", as that is standard // practice for exceptions, and may be useful for resources/foreach vars continue; } - addViolationWithMessage(ruleCtx, entry.rhs, makeMessage(entry, reason, entry.var.isField())); + addViolationWithMessage(ruleCtx, entry.rhs, makeMessage(entry, reason, entry.var instanceof JFieldSymbol)); } } } @@ -219,8 +232,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } private boolean suppressUnusedVariableRuleOverlap(AssignmentEntry entry) { - return !getProperty(REPORT_UNUSED_VARS) && (entry.rhs instanceof ASTVariableInitializer - || entry.rhs instanceof ASTVariableDeclaratorId); + return !getProperty(REPORT_UNUSED_VARS) && (entry.isInitializer() || entry.isBlankDeclaration()); } private static String getKind(ASTVariableDeclaratorId id) { @@ -230,7 +242,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return "resource"; } else if (id.isExceptionBlockParameter()) { return "exception parameter"; - } else if (id.getNthParent(3) instanceof ASTForStatement) { + } else if (id.getNthParent(3) instanceof ASTForeachStatement) { return "loop variable"; } else if (id.isFormalParameter()) { return "parameter"; @@ -242,7 +254,9 @@ public class UnusedAssignmentRule extends AbstractJavaRule { if (assignment instanceof ASTUnaryExpression) { // the variable value is used if it was found somewhere else // than in statement position - return !getProperty(CHECK_PREFIX_INCREMENT) && !(assignment.getParent() instanceof ASTExpressionStatement); + UnaryOp op = ((ASTUnaryExpression) assignment).getOperator(); + return !getProperty(CHECK_PREFIX_INCREMENT) && !op.isPure() && op.isPrefix() + && !(assignment.getParent() instanceof ASTExpressionStatement); } return false; } @@ -250,18 +264,18 @@ public class UnusedAssignmentRule extends AbstractJavaRule { private static String makeMessage(AssignmentEntry assignment, /* Nullable */ String reason, boolean isField) { // if reason is null, then the variable is unused (at most assigned to) - String varName = assignment.var.getName(); + String varName = assignment.var.getSimpleName(); StringBuilder result = new StringBuilder(64); - if (assignment.rhs instanceof ASTVariableInitializer) { + if (assignment.isInitializer()) { result.append(isField ? "the field initializer for" : "the initializer for variable"); - } else if (assignment.rhs instanceof ASTVariableDeclaratorId) { + } else if (assignment.isBlankDeclaration()) { if (reason != null) { result.append("the initial value of "); } - result.append(getKind(assignment.var)); - } else { - if (assignment.rhs instanceof ASTUnaryExpression) { + result.append(getKind(assignment.node)); + } else { // regular assignment + if (assignment.isUnaryReassign()) { result.append("the updated value of "); } else { result.append("the value assigned to "); @@ -280,14 +294,8 @@ public class UnusedAssignmentRule extends AbstractJavaRule { private static String joinLines(String prefix, Set killers) { StringBuilder sb = new StringBuilder(prefix); ArrayList sorted = new ArrayList<>(killers); - Collections.sort(sorted, new Comparator() { - @Override - public int compare(AssignmentEntry o1, AssignmentEntry o2) { - int lineRes = Integer.compare(o1.rhs.getBeginLine(), o2.rhs.getBeginLine()); - return lineRes != 0 ? lineRes - : Integer.compare(o1.rhs.getBeginColumn(), o2.rhs.getBeginColumn()); - } - }); + sorted.sort(Comparator.comparingInt((AssignmentEntry o) -> o.rhs.getBeginLine()) + .thenComparingInt(o -> o.rhs.getBeginColumn())); sb.append(sorted.get(0).rhs.getBeginLine()); for (int i = 1; i < sorted.size() - 1; i++) { @@ -301,19 +309,32 @@ public class UnusedAssignmentRule extends AbstractJavaRule { private static class ReachingDefsVisitor extends JavaVisitorBase { - static final ReachingDefsVisitor ONLY_LOCALS = new ReachingDefsVisitor(null); + static final ReachingDefsVisitor ONLY_LOCALS = new ReachingDefsVisitor(null, false); // The class scope for the "this" reference, used to find fields // of this class // null if we're not processing instance/static initializers, // so in methods we don't care about fields // If not null, fields are effectively treated as locals - private final ClassScope enclosingClassScope; + private final JClassSymbol enclosingClassScope; + private final boolean inStaticInit; - private ReachingDefsVisitor(ClassScope scope) { + private ReachingDefsVisitor(JClassSymbol scope, boolean inStaticInit) { this.enclosingClassScope = scope; + this.inStaticInit = inStaticInit; } + /** + * If true, we're also tracking fields of the {@code this} instance, + * because we're in a ctor or initializer. + */ + private boolean trackThisInstance() { + return enclosingClassScope != null && !inStaticInit; + } + + private boolean trackStaticFields() { + return enclosingClassScope != null && inStaticInit; + } // following deals with control flow structures @@ -337,17 +358,15 @@ public class UnusedAssignmentRule extends AbstractJavaRule { for (JavaNode child : node.children()) { // each output is passed as input to the next (most relevant for blocks) state = acceptOpt(child, state); - if (child instanceof ASTStatement - && child.getChild(0) instanceof ASTLocalVariableDeclaration) { - ASTLocalVariableDeclaration local = (ASTLocalVariableDeclaration) child.getChild(0); - for (ASTVariableDeclaratorId id : local) { + if (child instanceof ASTLocalVariableDeclaration) { + for (ASTVariableDeclaratorId id : (ASTLocalVariableDeclaration) child) { localsToKill.add(id); } } } for (ASTVariableDeclaratorId var : localsToKill) { - state.deleteVar(var); + state.deleteVar(var.getSymbol()); } return state; @@ -379,7 +398,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { current = global.breakTargets.doBreak(current, null); // process this as if it was followed by a break } else { // statement in a regular fallthrough switch block - current = acceptOpt(child, current); + current = acceptOpt(child, before.fork().absorb(current)); } } @@ -392,18 +411,15 @@ public class UnusedAssignmentRule extends AbstractJavaRule { @Override public SpanInfo visit(ASTIfStatement node, SpanInfo data) { - SpanInfo before = data; - return makeConditional(before, node.getCondition(), node.getThenBranch(), node.getElseBranch()); + return makeConditional(data, node.getCondition(), node.getThenBranch(), node.getElseBranch()); } @Override public SpanInfo visit(ASTConditionalExpression node, SpanInfo data) { - SpanInfo before = data; - return makeConditional(before, node.getCondition(), node.getChild(1), node.getChild(2)); + return makeConditional(data, node.getCondition(), node.getThenBranch(), node.getElseBranch()); } - // This will be much easier with the 7.0 grammar..... - SpanInfo makeConditional(SpanInfo before, JavaNode condition, JavaNode thenBranch, JavaNode elseBranch) { + SpanInfo makeConditional(SpanInfo before, ASTExpression condition, JavaNode thenBranch, JavaNode elseBranch) { SpanInfo thenState = before.fork(); SpanInfo elseState = elseBranch != null ? before.fork() : before; @@ -442,31 +458,31 @@ public class UnusedAssignmentRule extends AbstractJavaRule { * Eg for `a && b`, this is the `then` state (all evaluated to true) * */ - private SpanInfo linkConditional(SpanInfo before, JavaNode condition, SpanInfo thenState, SpanInfo elseState, boolean isTopLevel) { + private SpanInfo linkConditional(SpanInfo before, ASTExpression condition, SpanInfo thenState, SpanInfo elseState, boolean isTopLevel) { if (condition == null) { return before; } - condition = unwrapParentheses(condition); - if (condition instanceof ASTConditionalOrExpression) { - return visitShortcutOrExpr(condition, before, thenState, elseState); - } else if (condition instanceof ASTConditionalAndExpression) { - // To mimic a shortcut AND expr, swap the thenState and the elseState - // See explanations in method - return visitShortcutOrExpr(condition, before, elseState, thenState); - } else if (condition instanceof ASTExpression && condition.getNumChildren() == 1) { - return linkConditional(before, condition.getChild(0), thenState, elseState, isTopLevel); - } else { - SpanInfo state = acceptOpt(condition, before); - if (isTopLevel) { - thenState.absorb(state); - elseState.absorb(state); + if (condition instanceof ASTInfixExpression) { + BinaryOp op = ((ASTInfixExpression) condition).getOperator(); + if (op == BinaryOp.CONDITIONAL_OR) { + return visitShortcutOrExpr((ASTInfixExpression) condition, before, thenState, elseState); + } else if (op == BinaryOp.CONDITIONAL_AND) { + // To mimic a shortcut AND expr, swap the thenState and the elseState + // See explanations in method + return visitShortcutOrExpr((ASTInfixExpression) condition, before, elseState, thenState); } - return state; } + + SpanInfo state = acceptOpt(condition, before); + if (isTopLevel) { + thenState.absorb(state); + elseState.absorb(state); + } + return state; } - SpanInfo visitShortcutOrExpr(JavaNode orExpr, + SpanInfo visitShortcutOrExpr(ASTInfixExpression orExpr, SpanInfo before, SpanInfo thenState, SpanInfo elseState) { @@ -486,14 +502,11 @@ public class UnusedAssignmentRule extends AbstractJavaRule { // This method side effects on thenState and elseState to // set the variables. - Iterator iterator = orExpr.children().iterator(); - SpanInfo cur = before; - do { - JavaNode cond = iterator.next(); - cur = linkConditional(cur, cond, thenState, elseState, false); - thenState.absorb(cur); - } while (iterator.hasNext()); + cur = linkConditional(cur, orExpr.getLeftOperand(), thenState, elseState, false); + thenState.absorb(cur); + cur = linkConditional(cur, orExpr.getRightOperand(), thenState, elseState, false); + thenState.absorb(cur); elseState.absorb(cur); @@ -502,9 +515,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { @Override - public SpanInfo visit(ASTTryStatement node, SpanInfo data) { - final SpanInfo before = data; - ASTFinallyClause finallyClause = node.getFinallyClause(); + public SpanInfo visit(ASTTryStatement node, final SpanInfo before) { /* @@ -525,6 +536,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { reason (if the completes normally), which means it doesn't go to */ + ASTFinallyClause finallyClause = node.getFinallyClause(); if (finallyClause != null) { before.myFinally = before.forkEmpty(); @@ -532,7 +544,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { final List catchClauses = node.getCatchClauses().toList(); final List catchSpans = catchClauses.isEmpty() ? Collections.emptyList() - : new ArrayList(); + : new ArrayList<>(); // pre-fill catch spans for (int i = 0; i < catchClauses.size(); i++) { @@ -548,9 +560,11 @@ public class UnusedAssignmentRule extends AbstractJavaRule { bodyState = bodyState.withCatchBlocks(Collections.emptyList()); SpanInfo exceptionalState = null; + int i = 0; for (ASTCatchClause catchClause : node.getCatchClauses()) { - SpanInfo current = acceptOpt(catchClause, before.fork().absorb(bodyState)); + SpanInfo current = acceptOpt(catchClause, catchSpans.get(i)); exceptionalState = current.absorb(exceptionalState); + i++; } SpanInfo finalState; @@ -579,7 +593,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { @Override public SpanInfo visit(ASTCatchClause node, SpanInfo data) { SpanInfo result = visitJavaNode(node, data); - result.deleteVar(node.getParameter().getVarId()); + result.deleteVar(node.getParameter().getVarId().getSymbol()); return result; } @@ -630,12 +644,12 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } - private SpanInfo handleLoop(JavaNode loop, + private SpanInfo handleLoop(ASTLoopStatement loop, SpanInfo before, JavaNode init, - JavaNode cond, + ASTExpression cond, JavaNode update, - JavaNode body, + ASTStatement body, boolean checkFirstIter, ASTVariableDeclaratorId foreachVar) { final GlobalAlgoState globalState = before.global; @@ -657,7 +671,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { if (foreachVar != null) { // in foreach loops, the loop variable is assigned before the first iteration - before.assign(foreachVar, foreachVar); + before.assign(foreachVar.getSymbol(), foreachVar); } @@ -667,7 +681,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { if (foreachVar != null && iter.hasVar(foreachVar)) { // in foreach loops, the loop variable is reassigned on each update - iter.assign(foreachVar, foreachVar); + iter.assign(foreachVar.getSymbol(), foreachVar); } else { iter = acceptOpt(update, iter); } @@ -697,39 +711,39 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } if (foreachVar != null) { - result.deleteVar(foreachVar); + result.deleteVar(foreachVar.getSymbol()); } return result; } - private void pushTargets(JavaNode loop, SpanInfo breakTarget, SpanInfo continueTarget) { + private void pushTargets(ASTLoopStatement loop, SpanInfo breakTarget, SpanInfo continueTarget) { GlobalAlgoState globalState = breakTarget.global; globalState.breakTargets.unnamedTargets.push(breakTarget); globalState.continueTargets.unnamedTargets.push(continueTarget); - Node parent = loop.getNthParent(2); + Node parent = loop.getParent(); while (parent instanceof ASTLabeledStatement) { - String label = parent.getImage(); + String label = ((ASTLabeledStatement) parent).getLabel(); globalState.breakTargets.namedTargets.put(label, breakTarget); globalState.continueTargets.namedTargets.put(label, continueTarget); - parent = parent.getNthParent(2); + parent = parent.getParent(); } } - private SpanInfo popTargets(JavaNode loop, SpanInfo breakTarget, SpanInfo continueTarget) { + private SpanInfo popTargets(ASTLoopStatement loop, SpanInfo breakTarget, SpanInfo continueTarget) { GlobalAlgoState globalState = breakTarget.global; globalState.breakTargets.unnamedTargets.pop(); globalState.continueTargets.unnamedTargets.pop(); SpanInfo total = breakTarget.absorb(continueTarget); - Node parent = loop.getNthParent(2); + Node parent = loop.getParent(); while (parent instanceof ASTLabeledStatement) { - String label = parent.getImage(); + String label = ((ASTLabeledStatement) parent).getLabel(); total = total.absorb(globalState.breakTargets.namedTargets.remove(label)); total = total.absorb(globalState.continueTargets.namedTargets.remove(label)); - parent = parent.getNthParent(2); + parent = parent.getParent(); } return total; } @@ -775,248 +789,213 @@ public class UnusedAssignmentRule extends AbstractJavaRule { @Override public SpanInfo visit(ASTFormalParameter node, SpanInfo data) { - ASTVariableDeclaratorId id = node.getVarId(); - data.assign(id, id); + data.declareBlank(node.getVarId()); + return data; + } + + @Override + public SpanInfo visit(ASTCatchParameter node, SpanInfo data) { + data.declareBlank(node.getVarId()); return data; } @Override public SpanInfo visit(ASTVariableDeclarator node, SpanInfo data) { - ASTVariableDeclaratorId var = node.getVarId(); + JVariableSymbol var = node.getVarId().getSymbol(); ASTExpression rhs = node.getInitializer(); if (rhs != null) { rhs.acceptVisitor(this, data); data.assign(var, rhs); } else { - data.assign(var, node.getVarId()); + data.declareBlank(node.getVarId()); } return data; } @Override - public SpanInfo visit(ASTAssignmentExpression node, SpanInfo data) { - SpanInfo result = data; - ASTAssignableExpr lhs = node.getLeftOperand(); - ASTExpression rhs = node.getRightOperand(); + public SpanInfo visit(ASTUnaryExpression node, SpanInfo data) { + data = acceptOpt(node.getOperand(), data); - // visit the rhs as it is evaluated before - result = acceptOpt(rhs, result); - - ASTVariableDeclaratorId lhsVar = getVarFromExpression(lhs, true, result); - if (lhsVar != null) { - // in that case lhs is a normal variable (array access not supported) - - if (node.getOperator().isCompound()) { - // compound assignment, to use BEFORE assigning - result.use(lhsVar); - } - - result.assign(lhsVar, rhs); + if (node.getOperator().isPure()) { + return data; } else { - result = acceptOpt(lhs, result); + return processAssignment(node.getOperand(), node, true, data); + } + } + + @Override + public SpanInfo visit(ASTAssignmentExpression node, SpanInfo data) { + // visit operands in order + data = acceptOpt(node.getRightOperand(), data); + data = acceptOpt(node.getLeftOperand(), data); + + return processAssignment(node.getLeftOperand(), + node.getRightOperand(), + node.getOperator().isCompound(), + data); + + } + + private SpanInfo processAssignment(ASTExpression lhs, // LHS or unary operand + ASTExpression rhs, // RHS or unary + boolean useBeforeAssigning, + SpanInfo result) { + + if (lhs instanceof ASTNamedReferenceExpr) { + JVariableSymbol lhsVar = ((ASTNamedReferenceExpr) lhs).getReferencedSym(); + if (lhsVar != null + && (lhsVar instanceof JLocalVariableSymbol + || isRelevantField(lhs))) { + + if (useBeforeAssigning) { + // compound assignment, to use BEFORE assigning + result.use(lhsVar); + } + + result.assign(lhsVar, rhs); + } } return result; } - @Override - public SpanInfo visit(ASTUnaryExpression node, SpanInfo data) { - ASTVariableDeclaratorId var = getVarFromExpression(node.getChild(0), true, data); - if (var != null) { - data.use(var); - data.assign(var, node); + private boolean isRelevantField(ASTExpression lhs) { + if (!(lhs instanceof ASTNamedReferenceExpr)) { + return false; } - return data; + return trackThisInstance() && isThisFieldAccess(lhs) + || trackStaticFields() && isStaticFieldOfThisClass(((ASTNamedReferenceExpr) lhs).getReferencedSym()); + } + + private boolean isStaticFieldOfThisClass(JVariableSymbol var) { + return var instanceof JFieldSymbol + && ((JFieldSymbol) var).isStatic() + // must be non-null + && enclosingClassScope.equals(((JFieldSymbol) var).getEnclosingClass()); + } + + /** + * Whether the expression is an access to a field of this instance, + * not inherited, qualified or not ({@code this.field} or just {@code field}). + */ + private static boolean isThisFieldAccess(ASTExpression e) { + if (!(e instanceof ASTNamedReferenceExpr)) { + return false; + } + JVariableSymbol sym = ((ASTNamedReferenceExpr) e).getReferencedSym(); + if (sym instanceof JFieldSymbol) { + return !((JFieldSymbol) sym).isStatic() + // not inherited + && ((JFieldSymbol) sym).getEnclosingClass().equals(e.getEnclosingType().getSymbol()) + // correct syntactic form + && e instanceof ASTVariableAccess || isSyntacticThisFieldAccess(e); + } + return false; + } + + /** + * Whether the expression is a {@code this.field}, with no outer + * instance qualifier ({@code Outer.this.field}). The field symbol + * is not checked to resolve to a field declared in this class (it + * may be inherited) + */ + private static boolean isSyntacticThisFieldAccess(ASTExpression e) { + if (e instanceof ASTFieldAccess) { + ASTExpression qualifier = ((ASTFieldAccess) e).getQualifier(); + if (qualifier instanceof ASTThisExpression) { + // unqualified this + return ((ASTThisExpression) qualifier).getQualifier() == null; + } + } + return false; + } + + private static JVariableSymbol getVarIfUnaryAssignment(ASTUnaryExpression node) { + ASTExpression operand = node.getOperand(); + if (!node.getOperator().isPure() && operand instanceof ASTNamedReferenceExpr) { + return ((ASTNamedReferenceExpr) operand).getReferencedSym(); + } + return null; } // variable usage @Override - public SpanInfo visitPrimaryExpr(ASTPrimaryExpression node, SpanInfo data) { - SpanInfo state = visitJavaNode(node, data); // visit subexpressions - - ASTVariableDeclaratorId var = getVarFromExpression(node, false, state); - if (var != null) { - state.use(var); + public SpanInfo visit(ASTVariableAccess node, SpanInfo data) { + if (node.getAccessType() == AccessType.READ) { + data.use(node.getReferencedSym()); } + return data; + } - maybeThrowUncheckedExceptions(node, state); + @Override + public SpanInfo visit(ASTFieldAccess node, SpanInfo data) { + data = node.getQualifier().acceptVisitor(this, data); + if (isRelevantField(node) && node.getAccessType() == AccessType.READ) { + data.use(node.getReferencedSym()); + } + return data; + } + + @Override + public SpanInfo visit(ASTThisExpression node, SpanInfo data) { + if (trackThisInstance() && !(node.getParent() instanceof ASTFieldAccess)) { + data.recordThisLeak(true, enclosingClassScope); + } + return data; + } + + @Override + public SpanInfo visit(ASTMethodCall node, SpanInfo state) { + return visitInvocationExpr(node, state); + } + + @Override + public SpanInfo visit(ASTConstructorCall node, SpanInfo state) { + state = visitInvocationExpr(node, state); + acceptOpt(node.getAnonymousClassDeclaration(), state); return state; } - private void maybeThrowUncheckedExceptions(ASTPrimaryExpression e, SpanInfo state) { - // Note that this doesn't really respect the order of evaluation of subexpressions - // This can be easily fixed in the 7.0 tree, but this is rare enough to not deserve - // the effort on master. + private SpanInfo visitInvocationExpr(T node, SpanInfo state) { + state = acceptOpt(node.getQualifier(), state); + state = acceptOpt(node.getArguments(), state); - // For the record this has problems with call chains with side effects, like - // a.foo(a = 2).bar(a = 3); + // todo In 7.0, with the precise type/overload resolution, we + // could only target methods that throw checked exceptions + // (unless some catch block catches an unchecked exceptions) - // In 7.0, with the precise type/overload resolution, we - // could only target methods that throw checked exceptions - // (unless some catch block catches an unchecked exceptions) - for (JavaNode child : e.children()) { - if (child instanceof ASTPrimarySuffix && ((ASTPrimarySuffix) child).isArguments() - // fixme commented out on java-grammar - // || child instanceof ASTPrimarySuffix && child.getNumChildren() > 0 && child.getChild(0) instanceof ASTAllocationExpression - // || child instanceof ASTPrimaryPrefix && child.getNumChildren() > 0 && child.getChild(0) instanceof ASTAllocationExpression - ) { - state.abruptCompletionByThrow(true); // this is a noop if we're outside a try block that has catch/finally - } - } - } - - /** - * Get the variable accessed from a primary. - */ - private ASTVariableDeclaratorId getVarFromExpression(JavaNode primary, boolean inLhs, SpanInfo state) { - - if (primary instanceof ASTPrimaryExpression) { - ASTPrimaryPrefix prefix = (ASTPrimaryPrefix) primary.getChild(0); - - - // this.x = 2; - if (prefix.usesThisModifier() && this.enclosingClassScope != null) { - int numChildren = primary.getNumChildren(); - if (numChildren < 2 || numChildren > 2 && inLhs) { - if (numChildren == 3 || numChildren == 1) { - // method call on this, or just bare `this` reference - state.recordThisLeak(true, enclosingClassScope); - } - return null; - } - - ASTPrimarySuffix suffix = (ASTPrimarySuffix) primary.getChild(1); - if (suffix.getImage() == null) { - return null; - } else if (primary.getNumChildren() > 2 && ((ASTPrimarySuffix) primary.getChild(2)).isArguments()) { - // this.foo() - // first suffix is the name, second is the arguments - state.recordThisLeak(true, enclosingClassScope); - return null; - } - - return findVar(primary.getScope(), true, suffix.getImage()); - } else { - if (prefix.getNumChildren() > 0 && prefix.getChild(0) instanceof ASTName) { - String prefixImage = prefix.getChild(0).getImage(); - String varname = identOf(inLhs, prefixImage); - if (primary.getNumChildren() > 1) { - if (primary.getNumChildren() > 2 && inLhs) { - // this is for chains like `foo.m().field = 3` - return null; - } - ASTPrimarySuffix suffix = (ASTPrimarySuffix) primary.getChild(1); - if (suffix.isArguments()) { - // then the prefix has the method name - varname = methodLhsName(prefixImage); - } else if (suffix.isArrayDereference() && inLhs) { - return null; - } - } - return findVar(prefix.getScope(), false, varname); - } - } - } - - return null; - } - - private static String identOf(boolean inLhs, String str) { - int i = str.indexOf('.'); - if (i < 0) { - return str; - } else if (inLhs) { - // a qualified name in LHS, so - // the assignment doesn't assign the variable but one of its fields - return null; - } - return str.substring(0, i); - } - - private static String methodLhsName(String name) { - int i = name.indexOf('.'); - return i < 0 ? null // no lhs, the name is just the method name - : name.substring(0, i); - } - - private ASTVariableDeclaratorId findVar(Scope scope, boolean isField, String name) { - if (name == null) { - return null; - } - - if (isField) { - return getFromSingleScope(enclosingClassScope, name); - } - - while (scope != null) { - ASTVariableDeclaratorId result = getFromSingleScope(scope, name); - if (result != null) { - if (scope instanceof ClassScope && scope != enclosingClassScope) { // NOPMD CompareObjectsWithEqual this is what we want - // don't handle fields - return null; - } - return result; - } - - scope = scope.getParent(); - } - - return null; - } - - private ASTVariableDeclaratorId getFromSingleScope(Scope scope, String name) { - if (scope != null) { - for (VariableNameDeclaration decl : scope.getDeclarations(VariableNameDeclaration.class).keySet()) { - if (decl.getImage().equals(name)) { - return (ASTVariableDeclaratorId) decl.getNode(); - } - } - } - return null; + state.abruptCompletionByThrow(true); // this is a noop if we're outside a try block that has catch/finally + return state; } // ctor/initializer handling - // this is the common denominator between anonymous class & astAnyTypeDeclaration on master - @Override - public SpanInfo visit(ASTClassOrInterfaceBody node, SpanInfo data) { - visitTypeBody(node, data); - return data; // type doesn't contribute anything to the enclosing control flow - } + public SpanInfo visitTypeDecl(ASTAnyTypeDeclaration node, SpanInfo data) { + processInitializers(node.getDeclarations(), data, node.getSymbol()); - @Override - public SpanInfo visit(ASTEnumBody node, SpanInfo data) { - visitTypeBody(node, data); - return data; // type doesn't contribute anything to the enclosing control flow - } - - - private void visitTypeBody(ASTTypeBody typeBody, SpanInfo data) { - List declarations = typeBody.toList(); - processInitializers(declarations, data, (ClassScope) typeBody.getScope()); - - for (ASTBodyDeclaration decl : declarations) { + for (ASTBodyDeclaration decl : node.getDeclarations()) { if (decl instanceof ASTMethodDeclaration) { ASTMethodDeclaration method = (ASTMethodDeclaration) decl; if (method.getBody() != null) { ONLY_LOCALS.acceptOpt(decl, data.forkCapturingNonLocal()); } } else if (decl instanceof ASTAnyTypeDeclaration) { - ASTTypeBody body = (ASTTypeBody) decl.getChild(decl.getNumChildren() - 1); - visitTypeBody(body, data.forkEmptyNonLocal()); + visitTypeDecl((ASTAnyTypeDeclaration) decl, data.forkEmptyNonLocal()); } } + return data; // type doesn't contribute anything to the enclosing control flow } - private static void processInitializers(List declarations, + private static void processInitializers(NodeStream declarations, SpanInfo beforeLocal, - ClassScope scope) { + JClassSymbol classSymbol) { - ReachingDefsVisitor visitor = new ReachingDefsVisitor(scope); + ReachingDefsVisitor instanceVisitor = new ReachingDefsVisitor(classSymbol, false); + ReachingDefsVisitor staticVisitor = new ReachingDefsVisitor(classSymbol, true); // All field initializers + instance initializers SpanInfo ctorHeader = beforeLocal.forkCapturingNonLocal(); @@ -1039,33 +1018,31 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } if (isStatic) { - staticInit = visitor.acceptOpt(declaration, staticInit); + staticInit = staticVisitor.acceptOpt(declaration, staticInit); } else { - ctorHeader = visitor.acceptOpt(declaration, ctorHeader); + ctorHeader = instanceVisitor.acceptOpt(declaration, ctorHeader); } } SpanInfo ctorEndState = ctors.isEmpty() ? ctorHeader : null; for (ASTConstructorDeclaration ctor : ctors) { - SpanInfo state = visitor.acceptOpt(ctor, ctorHeader.forkCapturingNonLocal()); + SpanInfo state = instanceVisitor.acceptOpt(ctor, ctorHeader.forkCapturingNonLocal()); ctorEndState = ctorEndState == null ? state : ctorEndState.absorb(state); } - // assignments that reach the end of any constructor must - // be considered used - useAllSelfFields(staticInit, ctorEndState, visitor.enclosingClassScope); + // assignments that reach the end of any constructor must be considered used + useAllSelfFields(staticInit, ctorEndState, classSymbol); } - static void useAllSelfFields(/*nullable*/SpanInfo staticState, SpanInfo instanceState, ClassScope classScope) { - for (VariableNameDeclaration field : classScope.getVariableDeclarations().keySet()) { - ASTVariableDeclaratorId var = field.getDeclaratorId(); - if (field.getAccessNodeParent().isStatic()) { + static void useAllSelfFields(/*nullable*/SpanInfo staticState, SpanInfo instanceState, JClassSymbol enclosingSym) { + for (JFieldSymbol field : enclosingSym.getDeclaredFields()) { + if (field.isStatic()) { if (staticState != null) { - staticState.use(var); + staticState.use(field); } } else { - instanceState.use(var); + instanceState.use(field); } } } @@ -1098,22 +1075,24 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } private GlobalAlgoState() { - this(new HashSet(), - new HashSet(), - new HashMap>()); + this(new HashSet<>(), + new HashSet<>(), + new HashMap<>()); } } // Information about a variable in a code span. static class VarLocalInfo { - Set reachingDefs; + // this is not modified so can be shared between different SpanInfos. + final Set reachingDefs; VarLocalInfo(Set reachingDefs) { this.reachingDefs = reachingDefs; } - VarLocalInfo absorb(VarLocalInfo other) { + // and produce an independent instance + VarLocalInfo merge(VarLocalInfo other) { if (other == this) { return this; } @@ -1128,9 +1107,6 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return "VarLocalInfo{reachingDefs=" + reachingDefs + '}'; } - public VarLocalInfo copy() { - return new VarLocalInfo(this.reachingDefs); - } } /** @@ -1158,15 +1134,15 @@ public class UnusedAssignmentRule extends AbstractJavaRule { final GlobalAlgoState global; - final Map symtable; + final Map symtable; private SpanInfo(GlobalAlgoState global) { - this(null, global, new HashMap()); + this(null, global, new HashMap<>()); } private SpanInfo(SpanInfo parent, GlobalAlgoState global, - Map symtable) { + Map symtable) { this.parent = parent; this.global = global; this.symtable = symtable; @@ -1174,11 +1150,19 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } boolean hasVar(ASTVariableDeclaratorId var) { - return symtable.containsKey(var); + return symtable.containsKey(var.getSymbol()); } - void assign(ASTVariableDeclaratorId var, JavaNode rhs) { - AssignmentEntry entry = new AssignmentEntry(var, rhs); + void declareBlank(ASTVariableDeclaratorId id) { + assign(id.getSymbol(), id); + } + + void assign(JVariableSymbol var, JavaNode rhs) { + ASTVariableDeclaratorId node = var.tryGetNode(); + if (node == null) { + return; // we don't care about non-local declarations + } + AssignmentEntry entry = new AssignmentEntry(var, node, rhs); VarLocalInfo previous = symtable.put(var, new VarLocalInfo(Collections.singleton(entry))); if (previous != null) { // those assignments were overwritten ("killed") @@ -1188,19 +1172,15 @@ public class UnusedAssignmentRule extends AbstractJavaRule { && killed.rhs != rhs) { continue; } - // java8: computeIfAbsent - Set killers = global.killRecord.get(killed); - if (killers == null) { - killers = new HashSet<>(1); - global.killRecord.put(killed, killers); - } - killers.add(entry); + + global.killRecord.computeIfAbsent(killed, k -> new HashSet<>(1)) + .add(entry); } } global.allAssignments.add(entry); } - void use(ASTVariableDeclaratorId var) { + void use(@Nullable JVariableSymbol var) { VarLocalInfo info = symtable.get(var); // may be null for implicit assignments, like method parameter if (info != null) { @@ -1208,7 +1188,7 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } } - void deleteVar(ASTVariableDeclaratorId var) { + void deleteVar(JVariableSymbol var) { symtable.remove(var); } @@ -1232,10 +1212,10 @@ public class UnusedAssignmentRule extends AbstractJavaRule { * of `this`. So the analysis may show some false positives, which * hopefully should be rare enough. */ - public void recordThisLeak(boolean thisIsLeaking, ClassScope enclosingClassScope) { - if (thisIsLeaking && enclosingClassScope != null) { + public void recordThisLeak(boolean thisIsLeaking, JClassSymbol enclosingClassSym) { + if (thisIsLeaking && enclosingClassSym != null) { // all reaching defs to fields until now may be observed - ReachingDefsVisitor.useAllSelfFields(null, this, enclosingClassScope); + ReachingDefsVisitor.useAllSelfFields(null, this, enclosingClassSym); } } @@ -1248,27 +1228,23 @@ public class UnusedAssignmentRule extends AbstractJavaRule { } SpanInfo forkEmpty() { - return doFork(this, new HashMap()); + return doFork(this, new HashMap<>()); } SpanInfo forkEmptyNonLocal() { - return doFork(null, new HashMap()); + return doFork(null, new HashMap<>()); } SpanInfo forkCapturingNonLocal() { return doFork(null, copyTable()); } - private Map copyTable() { - HashMap copy = new HashMap<>(this.symtable.size()); - for (ASTVariableDeclaratorId var : this.symtable.keySet()) { - copy.put(var, this.symtable.get(var).copy()); - } - return copy; + private Map copyTable() { + return new HashMap<>(this.symtable); } - private SpanInfo doFork(/*nullable*/ SpanInfo parent, Map reaching) { + private SpanInfo doFork(/*nullable*/ SpanInfo parent, Map reaching) { return new SpanInfo(parent, this.global, reaching); } @@ -1347,22 +1323,9 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return this; } - // we don't have to double the capacity since they're normally of the same size - // (vars are deleted when exiting a block) - Set keysUnion = new HashSet<>(this.symtable.keySet()); - keysUnion.addAll(other.symtable.keySet()); - - for (ASTVariableDeclaratorId var : keysUnion) { - VarLocalInfo thisInfo = this.symtable.get(var); - VarLocalInfo otherInfo = other.symtable.get(var); - if (thisInfo == otherInfo) { // NOPMD CompareObjectsWithEqual this is what we want - continue; - } - if (otherInfo != null && thisInfo != null) { - this.symtable.put(var, thisInfo.absorb(otherInfo)); - } else if (otherInfo != null) { - this.symtable.put(var, otherInfo.copy()); - } + for (JVariableSymbol var : other.symtable.keySet()) { + VarLocalInfo otherInfo = other.symtable.get(var); // non-null + this.symtable.merge(var, otherInfo, VarLocalInfo::merge); } return this; } @@ -1410,20 +1373,36 @@ public class UnusedAssignmentRule extends AbstractJavaRule { static class AssignmentEntry { - final ASTVariableDeclaratorId var; + final JVariableSymbol var; + final ASTVariableDeclaratorId node; // this is not necessarily an expression, it may be also the // variable declarator of a foreach loop final JavaNode rhs; - AssignmentEntry(ASTVariableDeclaratorId var, JavaNode rhs) { + AssignmentEntry(JVariableSymbol var, ASTVariableDeclaratorId node, JavaNode rhs) { this.var = var; + this.node = node; this.rhs = rhs; } + boolean isInitializer() { + return rhs.getParent() instanceof ASTVariableDeclarator + && rhs.getIndexInParent() > 0; + } + + boolean isBlankDeclaration() { + return rhs instanceof ASTVariableDeclaratorId; + } + + boolean isUnaryReassign() { + return rhs instanceof ASTUnaryExpression + && ReachingDefsVisitor.getVarIfUnaryAssignment((ASTUnaryExpression) rhs) == var; + } + @Override public String toString() { - return var.getName() + " := " + rhs; + return var.getSimpleName() + " := " + rhs; } @Override @@ -1435,12 +1414,13 @@ public class UnusedAssignmentRule extends AbstractJavaRule { return false; } AssignmentEntry that = (AssignmentEntry) o; - return Objects.equals(rhs, that.rhs); + return Objects.equals(var, that.var) + && Objects.equals(rhs, that.rhs); } @Override public int hashCode() { - return rhs.hashCode(); + return 31 * var.hashCode() + rhs.hashCode(); } } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRule.java deleted file mode 100644 index 58f39f54ef..0000000000 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRule.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.documentation; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import net.sourceforge.pmd.annotation.InternalApi; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.lang.ast.NodeStream; -import net.sourceforge.pmd.lang.ast.impl.javacc.JjtreeNode; -import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceBody; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTPackageDeclaration; -import net.sourceforge.pmd.lang.java.ast.AccessNode; -import net.sourceforge.pmd.lang.java.ast.Comment; -import net.sourceforge.pmd.lang.java.ast.CommentUtil; -import net.sourceforge.pmd.lang.java.ast.FormalComment; -import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.JavadocElement; -import net.sourceforge.pmd.lang.java.ast.TypeNode; -import net.sourceforge.pmd.lang.java.javadoc.JavadocTag; -import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; -import net.sourceforge.pmd.util.CollectionUtil; -import net.sourceforge.pmd.util.DataMap; -import net.sourceforge.pmd.util.DataMap.SimpleDataKey; - -/** - * @author Brian Remedios - * @deprecated Internal API - */ -@Deprecated -@InternalApi -public abstract class AbstractCommentRule extends AbstractJavaRule { - - public static final SimpleDataKey COMMENT_KEY = DataMap.simpleDataKey("java.comment"); - - /** - * Returns a list of indices of javadoc tag occurrences in the comment. - * - *

    Note: if the same tag occurs multiple times, only the last occurrence is returned. - * - * @param comments the complete comment text - * @return list of indices. - * - * @deprecated This method is deprecated and will be removed with PMD 7.0.0. - * It is not very useful, since it doesn't extract the information - * in a useful way. You would still need check, which tags have been found, and with which - * data they might be accompanied. - * A more useful solution will be added around the AST node {@link FormalComment}, - * which contains as children {@link JavadocElement} nodes, which in - * turn provide access to the {@link JavadocTag}. - */ - @Deprecated // the method will be removed with PMD 7.0.0 - protected List tagsIndicesIn(String comments) { - Map tags = CommentUtil.javadocTagsIn(comments); - return new ArrayList<>(tags.values()); - } - - protected String filteredCommentIn(Comment comment) { - return comment.getFilteredComment(); - } - - protected static Comment getComment(JavaNode node) { - return node.getUserMap().get(COMMENT_KEY); - } - - protected void assignCommentsToDeclarations(ASTCompilationUnit cUnit) { - // FIXME make that a processing stage! - - List> itemsByLineNumber = orderedCommentsAndDeclarations(cUnit); - FormalComment lastComment = null; - JavaNode lastNode = null; - - for (JjtreeNode value : itemsByLineNumber) { - if (!(value instanceof Comment)) { - JavaNode node = (JavaNode) value; - // maybe the last comment is within the last node - if (lastComment != null - && isCommentNotWithin(lastComment, lastNode, node) - && isCommentBefore(lastComment, node)) { - node.getUserMap().set(COMMENT_KEY, lastComment); - lastComment = null; - } - if (node instanceof ASTMethodOrConstructorDeclaration) { - lastNode = node; - } - } else if (value instanceof FormalComment) { - lastComment = (FormalComment) value; - } - } - } - - private boolean isCommentNotWithin(FormalComment n1, JjtreeNode n2, JjtreeNode node) { - if (n1 == null || n2 == null || node == null) { - return true; - } - boolean isNotWithinNode2 = !n2.getTextRegion().contains(n1.getTextRegion()); - boolean isNotSameClass = - node.getFirstParentOfType(ASTClassOrInterfaceBody.class) - != n2.getFirstParentOfType(ASTClassOrInterfaceBody.class); - boolean isNodeWithinNode2 = n2.getTextRegion().contains(node.getTextRegion()); - return isNotWithinNode2 || isNotSameClass || isNodeWithinNode2; - } - - private boolean isCommentBefore(FormalComment n1, JjtreeNode n2) { - return n1.getTextRegion().compareTo(n2.getTextRegion()) <= 0; - } - - protected List> orderedCommentsAndDeclarations(ASTCompilationUnit cUnit) { - List> itemsByLineNumber = - cUnit.descendants() - .crossFindBoundaries() - .>map(NodeStream.asInstanceOf(ASTAnyTypeDeclaration.class, ASTFieldDeclaration.class, ASTMethodDeclaration.class, ASTConstructorDeclaration.class)) - .collect(CollectionUtil.toMutableList()); - - itemsByLineNumber.addAll(cUnit.getComments()); - ASTPackageDeclaration pack = cUnit.getPackageDeclaration(); - if (pack != null) { - itemsByLineNumber.add(pack); - } - itemsByLineNumber.sort(Node::compareLocation); - - return itemsByLineNumber; - } -} diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java index e9ffd8a54b..eac9932f67 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentRule.java @@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.Comment; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertySource; @@ -29,7 +30,7 @@ import net.sourceforge.pmd.properties.PropertySource; * * @author Brian Remedios */ -public class CommentContentRule extends AbstractCommentRule { +public class CommentContentRule extends AbstractJavaRule { private boolean caseSensitive; private List originalBadWords; @@ -78,7 +79,7 @@ public class CommentContentRule extends AbstractCommentRule { return Collections.emptyList(); } - String commentText = filteredCommentIn(comment); + String commentText = comment.getFilteredComment(); if (StringUtils.isBlank(commentText)) { return Collections.emptyList(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java index 017d9d4f64..78cabc82e2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredRule.java @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.java.rule.documentation; +import java.io.ObjectStreamField; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -15,14 +16,18 @@ import java.util.logging.Logger; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.AccessNode; +import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration; +import net.sourceforge.pmd.lang.java.ast.JModifier; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.ast.JavadocCommentOwner; import net.sourceforge.pmd.lang.java.multifile.signature.JavaOperationSignature; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; +import net.sourceforge.pmd.lang.java.types.TypeTestUtil; import net.sourceforge.pmd.properties.PropertyBuilder.GenericPropertyBuilder; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; @@ -31,7 +36,7 @@ import net.sourceforge.pmd.properties.PropertyFactory; /** * @author Brian Remedios */ -public class CommentRequiredRule extends AbstractCommentRule { +public class CommentRequiredRule extends AbstractJavaRule { private static final Logger LOG = Logger.getLogger(CommentRequiredRule.class.getName()); // Used to pretty print a message @@ -106,18 +111,18 @@ public class CommentRequiredRule extends AbstractCommentRule { } } - private void checkCommentMeetsRequirement(Object data, JavaNode node, + private void checkCommentMeetsRequirement(Object data, JavadocCommentOwner node, PropertyDescriptor descriptor) { switch (propertyValues.get(descriptor)) { case Ignored: break; case Required: - if (getComment(node) == null) { + if (node.getJavadocComment() == null) { commentRequiredViolation(data, node, descriptor); } break; case Unwanted: - if (getComment(node) != null) { + if (node.getJavadocComment() != null) { commentRequiredViolation(data, node, descriptor); } break; @@ -166,7 +171,7 @@ public class CommentRequiredRule extends AbstractCommentRule { } - private void checkMethodOrConstructorComment(AccessNode decl, Object data) { + private void checkMethodOrConstructorComment(ASTMethodOrConstructorDeclaration decl, Object data) { if (decl.isPublic()) { checkCommentMeetsRequirement(data, decl, PUB_METHOD_CMT_REQUIREMENT_DESCRIPTOR); } else if (decl.isProtected()) { @@ -196,11 +201,9 @@ public class CommentRequiredRule extends AbstractCommentRule { @SuppressWarnings("PMD.UnusedFormalParameter") private boolean isSerialVersionUID(ASTFieldDeclaration field) { - return false; // FIXME, commented out because of incompatibility, needs typeres - // return "serialVersionUID".equals(field.getVariableName()) - // && field.isStatic() - // && field.isFinal() - // && field.getType() == long.class; + return field.getVarIds().any(it -> "serialVersionUID".equals(it.getName())) + && field.hasModifiers(JModifier.FINAL, JModifier.STATIC) + && field.getTypeNode().getTypeMirror().isPrimitive(PrimitiveTypeKind.LONG); } /** @@ -215,13 +218,9 @@ public class CommentRequiredRule extends AbstractCommentRule { */ @SuppressWarnings("PMD.UnusedFormalParameter") private boolean isSerialPersistentFields(final ASTFieldDeclaration field) { - return false; // FIXME, commented out because of incompatibility, needs typeres - // return "serialPersistentFields".equals(field.getVariableName()) - // && field.isPrivate() - // && field.isStatic() - // && field.isFinal() - // && field.isArray() - // && "ObjectStreamField".equals(field.getFirstToken().getImage()); // .getType() returns null + return field.getVarIds().any(it -> "serialPersistentFields".equals(it.getName())) + && field.hasModifiers(JModifier.FINAL, JModifier.STATIC, JModifier.PRIVATE) + && TypeTestUtil.isA(ObjectStreamField[].class, field.getTypeNode()); } @Override @@ -230,12 +229,6 @@ public class CommentRequiredRule extends AbstractCommentRule { return super.visit(decl, data); } - @Override - public Object visit(ASTCompilationUnit cUnit, Object data) { - assignCommentsToDeclarations(cUnit); - return super.visit(cUnit, data); - } - private boolean allCommentsAreIgnored() { return getProperty(OVERRIDE_CMT_DESCRIPTOR) == CommentRequirement.Ignored diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java index 84bfd46837..a00d8a1771 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeRule.java @@ -15,6 +15,7 @@ import org.apache.commons.lang3.StringUtils; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.Comment; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.properties.PropertyFactory; import net.sourceforge.pmd.util.StringUtil; @@ -24,7 +25,7 @@ import net.sourceforge.pmd.util.StringUtil; * * @author Brian Remedios */ -public class CommentSizeRule extends AbstractCommentRule { +public class CommentSizeRule extends AbstractJavaRule { public static final PropertyDescriptor MAX_LINES = PropertyFactory.intProperty("maxLines") diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java index f8d486ea9e..3f2058eb54 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/CloseResourceRule.java @@ -37,6 +37,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix; import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix; import net.sourceforge.pmd.lang.java.ast.ASTResourceList; import net.sourceforge.pmd.lang.java.ast.ASTReturnStatement; +import net.sourceforge.pmd.lang.java.ast.ASTStatementExpression; import net.sourceforge.pmd.lang.java.ast.ASTTryStatement; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclarator; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; @@ -44,6 +45,7 @@ import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; import net.sourceforge.pmd.lang.java.types.TypeTestUtil; +import net.sourceforge.pmd.lang.symboltable.NameDeclaration; import net.sourceforge.pmd.properties.PropertyDescriptor; /** @@ -65,6 +67,7 @@ import net.sourceforge.pmd.properties.PropertyDescriptor; public class CloseResourceRule extends AbstractJavaRule { private static final String WRAPPING_TRY_WITH_RES_VAR_MESSAGE = "it is recommended to wrap resource in try-with-resource declaration directly"; + private static final String REASSIGN_BEFORE_CLOSED_MESSAGE = "'' is reassigned, but the original instance is not closed"; private static final String CLOSE_IN_FINALLY_BLOCK_MESSAGE = "'' is not closed within a finally block, thus might not be closed at all in case of exceptions"; private static final PropertyDescriptor> CLOSE_TARGETS_DESCRIPTOR = @@ -164,6 +167,12 @@ public class CloseResourceRule extends AbstractJavaRule { } else if (shouldVarOfTypeBeClosedInMethod(resVar, resVarType, methodOrConstructor)) { reportedVarNames.add(resVar.getVarId().getName()); addCloseResourceViolation(resVar.getVarId(), resVarType, data); + } else { + ASTStatementExpression reassigningStatement = getFirstReassigningStatementBeforeBeingClosed(resVar, methodOrConstructor); + if (reassigningStatement != null) { + reportedVarNames.add(resVar.getVarId().getName()); + addViolationWithMessage(data, reassigningStatement, reassignBeforeClosedMessageForVar(resVar.getName())); + } } } } @@ -173,7 +182,7 @@ public class CloseResourceRule extends AbstractJavaRule { Map resVars = new HashMap<>(); for (ASTVariableDeclarator var : vars) { TypeNode varType = getTypeOfVariable(var); - if (isResourceTypeOrSubtype(varType)) { + if (varType != null && isResourceTypeOrSubtype(varType)) { resVars.put(var, wrappedResourceTypeOrReturn(var, varType)); } } @@ -187,7 +196,7 @@ public class CloseResourceRule extends AbstractJavaRule { private TypeNode getDeclaredTypeOfVariable(ASTVariableDeclarator var) { ASTLocalVariableDeclaration localVar = (ASTLocalVariableDeclaration) var.getParent(); - return localVar.getTypeNode(); + return localVar.getTypeNode(); // note: can be null, if type is inferred (var) } private TypeNode getRuntimeTypeOfVariable(ASTVariableDeclarator var) { @@ -660,4 +669,77 @@ public class CloseResourceRule extends AbstractJavaRule { private String closeInFinallyBlockMessageForVar(String var) { return "''" + var + CLOSE_IN_FINALLY_BLOCK_MESSAGE; } + + private String reassignBeforeClosedMessageForVar(String var) { + return "''" + var + REASSIGN_BEFORE_CLOSED_MESSAGE; + } + + private ASTStatementExpression getFirstReassigningStatementBeforeBeingClosed(ASTVariableDeclarator variable, ASTMethodOrConstructorDeclaration methodOrConstructor) { + List statements = methodOrConstructor.findDescendantsOfType(ASTStatementExpression.class); + boolean variableClosed = false; + boolean isInitialized = !hasNullInitializer(variable); + ASTExpression initializingExpression = initializerExpressionOf(variable); + for (ASTStatementExpression statement : statements) { + if (isClosingVariableStatement(statement, variable)) { + variableClosed = true; + } + + if (isAssignmentForVariable(statement, variable)) { + if (isInitialized && !variableClosed) { + if (initializingExpression != null && !inSameIfBlock(statement, initializingExpression)) { + return statement; + } + } + + if (variableClosed) { + variableClosed = false; + } + if (!isInitialized) { + isInitialized = true; + initializingExpression = statement.getFirstDescendantOfType(ASTExpression.class); + } + } + } + return null; + } + + private boolean inSameIfBlock(ASTStatementExpression statement1, ASTExpression statement2) { + List parents1 = statement1.getParentsOfType(ASTIfStatement.class); + List parents2 = statement2.getParentsOfType(ASTIfStatement.class); + parents1.retainAll(parents2); + return !parents1.isEmpty(); + } + + private boolean isClosingVariableStatement(ASTStatementExpression statement, ASTVariableDeclarator variable) { + List expressions = statement.findDescendantsOfType(ASTPrimaryExpression.class); + for (ASTPrimaryExpression expression : expressions) { + if (isMethodCallClosingResourceVariable(expression, variable.getName())) { + return true; + } + } + List names = statement.findDescendantsOfType(ASTName.class); + for (ASTName name : names) { + if (isCloseCallOnVariable(name, variable.getName())) { + return true; + } + } + return false; + } + + private boolean isAssignmentForVariable(ASTStatementExpression statement, ASTVariableDeclarator variable) { + if (statement == null || variable == null) { + return false; + } + ASTName name = statement.getFirstDescendantOfType(ASTName.class); + if (name == null) { + return false; + } + NameDeclaration statementVariable = name.getNameDeclaration(); + if (statementVariable == null) { + return false; + } + + return statement.hasDescendantOfType(ASTAssignmentOperator.class) + && statementVariable.equals(variable.getVarId().getNameDeclaration()); + } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleViolationFactory.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleViolationFactory.java index 198bcdd16b..d34341df71 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleViolationFactory.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/internal/JavaRuleViolationFactory.java @@ -15,6 +15,8 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.ViolationSuppressor; import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; +import net.sourceforge.pmd.lang.java.ast.InternalApiBridge; import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.rule.JavaRuleViolation; import net.sourceforge.pmd.lang.rule.RuleViolationFactory; @@ -48,8 +50,14 @@ public final class JavaRuleViolationFactory extends DefaultRuleViolationFactory } @Override - public RuleViolation createViolation(Rule rule, @NonNull Node location, String filename, String formattedMessage) { - return new JavaRuleViolation(rule, (JavaNode) location, filename, formattedMessage); + public RuleViolation createViolation(Rule rule, @NonNull Node location, @NonNull String formattedMessage) { + JavaNode javaNode = (JavaNode) location; + JavaRuleViolation violation = new JavaRuleViolation(rule, javaNode, formattedMessage); + JavaccToken preferredLoc = InternalApiBridge.getReportLocation(javaNode); + if (preferredLoc != null) { + violation.setLines(preferredLoc.getBeginLine(), preferredLoc.getEndLine()); + } + return violation; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/security/TypeResTestRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/security/TypeResTestRule.java index 0e5430b565..23740b5777 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/security/TypeResTestRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/security/TypeResTestRule.java @@ -25,9 +25,6 @@ import net.sourceforge.pmd.util.StringUtil; @SuppressWarnings("PMD") public class TypeResTestRule extends AbstractJavaRule { - public static final ThreadLocal FILENAME = - ThreadLocal.withInitial(() -> "/*unknown*/"); - private static class State { public int fileId = 0; @@ -69,7 +66,6 @@ public class TypeResTestRule extends AbstractJavaRule { @Override public Object visit(ASTCompilationUnit node, Object data) { - FILENAME.set(node.getSourceCodeFile()); for (JavaNode descendant : node.descendants().crossFindBoundaries()) { visitJavaNode(descendant, data); } @@ -113,7 +109,7 @@ public class TypeResTestRule extends AbstractJavaRule { @NonNull public String position(JavaNode node) { - return "In: " + node.getSourceCodeFile() + ":" + node.getBeginLine() + ":" + node.getBeginColumn(); + return "In: " + node.getTextDocument().getDisplayName() + ":" + node.getBeginLine() + ":" + node.getBeginColumn(); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JAccessibleElementSymbol.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JAccessibleElementSymbol.java index a651286cd3..00b718a0db 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JAccessibleElementSymbol.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/JAccessibleElementSymbol.java @@ -32,6 +32,11 @@ public interface JAccessibleElementSymbol extends JElementSymbol { int getModifiers(); + default boolean isStatic() { + return Modifier.isStatic(getModifiers()); + } + + /** * Returns the class that directly encloses this declaration. * This is equivalent to {@link Class#getEnclosingClass()}. diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstClassSym.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstClassSym.java index 85b1abac2f..2f280ad985 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstClassSym.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstClassSym.java @@ -4,8 +4,6 @@ package net.sourceforge.pmd.lang.java.symbols.internal.ast; -import static net.sourceforge.pmd.util.CollectionUtil.listOf; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -199,10 +197,13 @@ final class AstClassSym @Override public @Nullable JClassType getSuperclassType(Substitution substitution) { TypeSystem ts = getTypeSystem(); - if (node instanceof ASTEnumDeclaration) { - JClassSymbol enumClass = ts.getClassSymbol(Enum.class); - return (JClassType) ts.parameterise(enumClass, listOf(ts.declaration(this))); + + if (node.isEnum()) { + + return factory.enumSuperclass(this); + } else if (node instanceof ASTClassOrInterfaceDeclaration) { + ASTClassOrInterfaceType superClass = ((ASTClassOrInterfaceDeclaration) node).getSuperClassTypeNode(); return superClass == null ? ts.OBJECT @@ -223,9 +224,17 @@ final class AstClassSym ? (JClassType) sym : factory.types().OBJECT; } + + } else if (isRecord()) { + + return factory.recordSuperclass(); + + } else if (isAnnotation()) { + + return ts.OBJECT; + } - // TODO records return null; } @@ -234,13 +243,25 @@ final class AstClassSym // notice this relies on the fact that the extends clause // (or the type node of the constructor call, for an anonymous class), // was disambiguated early + + // We special case anonymous classes so as not to trigger overload resolution + if (isAnonymousClass() && node.getParent() instanceof ASTConstructorCall) { + + @NonNull JTypeMirror sym = ((ASTConstructorCall) node.getParent()).getTypeNode().getTypeMirror(); + + return sym instanceof JClassType && !sym.isInterface() + ? ((JClassType) sym).getSymbol() + : factory.types().OBJECT.getSymbol(); + + } + JClassType sup = getSuperclassType(Substitution.EMPTY); return sup == null ? null : sup.getSymbol(); } @Override public List getSuperInterfaces() { - return CollectionUtil.mapNotNull( + List itfs = CollectionUtil.mapNotNull( node.getSuperInterfaceTypeNodes(), n -> { // we play safe here, but the symbol is either a JClassSymbol @@ -250,11 +271,19 @@ final class AstClassSym return sym instanceof JClassSymbol ? (JClassSymbol) sym : null; } ); + if (isAnnotation()) { + itfs = CollectionUtil.concatView(Collections.singletonList(factory.annotationSym()), itfs); + } + return itfs; } @Override public List getSuperInterfaceTypes(Substitution subst) { - return CollectionUtil.map(node.getSuperInterfaceTypeNodes(), n -> (JClassType) TypeOps.subst(n.getTypeMirror(), subst)); + List itfs = CollectionUtil.map(node.getSuperInterfaceTypeNodes(), n -> (JClassType) TypeOps.subst(n.getTypeMirror(), subst)); + if (isAnnotation()) { + itfs = CollectionUtil.concatView(Collections.singletonList(factory.annotationType()), itfs); + } + return itfs; } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstSymFactory.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstSymFactory.java index 137cfe43d5..5a4288a5ed 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstSymFactory.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/AstSymFactory.java @@ -4,12 +4,16 @@ package net.sourceforge.pmd.lang.java.symbols.internal.ast; +import static net.sourceforge.pmd.util.CollectionUtil.listOf; + import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.internal.JavaAstProcessor; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; import net.sourceforge.pmd.lang.java.symbols.JTypeParameterOwnerSymbol; +import net.sourceforge.pmd.lang.java.types.JClassType; import net.sourceforge.pmd.lang.java.types.TypeSystem; @@ -17,9 +21,29 @@ final class AstSymFactory { private final TypeSystem ts; + private final JavaAstProcessor processor; - AstSymFactory(TypeSystem ts) { - this.ts = ts; + + AstSymFactory(JavaAstProcessor processor) { + this.ts = processor.getTypeSystem(); + this.processor = processor; + } + + JClassType recordSuperclass() { + return (JClassType) ts.declaration(processor.findSymbolCannotFail("java.lang.Record")); + } + + JClassType enumSuperclass(JClassSymbol enumT) { + return (JClassType) ts.parameterise(processor.findSymbolCannotFail("java.lang.Enum"), + listOf(ts.declaration(enumT))); + } + + JClassSymbol annotationSym() { + return processor.findSymbolCannotFail("java.lang.annotation.Annotation"); + } + + JClassType annotationType() { + return (JClassType) ts.declaration(annotationSym()); } public TypeSystem types() { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/SymbolResolutionPass.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/SymbolResolutionPass.java index 0ec32aa675..ca4d71b744 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/SymbolResolutionPass.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/ast/SymbolResolutionPass.java @@ -31,7 +31,7 @@ public final class SymbolResolutionPass { */ public static SymbolResolver traverse(JavaAstProcessor processor, ASTCompilationUnit root) { AstSymbolMakerVisitor visitor = new AstSymbolMakerVisitor(root); - root.acceptVisitor(visitor, new AstSymFactory(processor.getTypeSystem())); + root.acceptVisitor(visitor, new AstSymFactory(processor)); return visitor.makeKnownSymbolResolver(); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SemanticChecksLogger.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/JavaSemanticErrors.java similarity index 65% rename from pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SemanticChecksLogger.java rename to pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/JavaSemanticErrors.java index 4202caab0e..284acfcab7 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SemanticChecksLogger.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/JavaSemanticErrors.java @@ -4,16 +4,10 @@ package net.sourceforge.pmd.lang.java.symbols.table.internal; -import java.text.MessageFormat; - -import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.ast.internal.LanguageLevelChecker; - /** - * TODO pull that up to PMD core, use for {@link LanguageLevelChecker} - * as well + * */ -public interface SemanticChecksLogger { +public final class JavaSemanticErrors { // TODO how strict do we need to be here? // many rules don't absolutely need correctness to work @@ -22,46 +16,6 @@ public interface SemanticChecksLogger { // level 1: parsable (many syntax-only rules, eg UnnecessaryParentheses) // level 2: type-resolved (more complicated rules) - /** - * Warning, classpath is misconfigured (or not configured). - */ - String CANNOT_RESOLVE_SYMBOL = "Cannot resolve symbol {0}"; - String INACCESSIBLE_SYMBOL = "Symbol {0} is inaccessible"; - - - /** - * We had resolved a prefix, and a suffix is not resolved. This may - * mean that the classpath is out-of-date, or the code is incorrect. - * Eg {@code System.oute}: {@code System} is resolved, {@code oute} - * is not a member of that type. - * - *

    This differs from {@link #CANNOT_RESOLVE_SYMBOL} in that for - * the latter, it's more probable that the classpath is incorrect. - * It is emitted eg when we see an import, so a fully qualified - * name, and yet we can't resolve it. - * TODO whether it's incorrect code or incorrect classpath is only - * a guess, probably we need an option to differentiate the two - * (eg in an IDE plugin, it may well be incorrect code, but in a - * CLI run, it's more likely to be incorrect classpath). - */ - String CANNOT_RESOLVE_MEMBER = "Cannot resolve ''{0}'' in {1}, treating it as {2}"; // javac gives a simple "cannot resolve symbol {0}" - - /** - * TODO Should be an error. - */ - String MALFORMED_GENERIC_TYPE = "Maformed generic type: expected {0} type arguments, got {1}"; - - // this is an error - String EXPECTED_ANNOTATION_TYPE = "Expected an annotation type"; - - /** - * An ambiguous name is completely ambiguous. We don't have info - * about it at all, classpath is incomplete or code is incorrect. - * Eg {@code package.that.doesnt.exist.Type} - */ - String CANNOT_RESOLVE_AMBIGUOUS_NAME = "Cannot resolve ambiguous name {0}, treating it as {1}"; - - String AMBIGUOUS_NAME_REFERENCE = "Reference ''{0}'' is ambiguous, both {1} and {2} match"; /* TODO Checks that are essential for typeres/symtable @@ -79,16 +33,43 @@ public interface SemanticChecksLogger { to be more lenient) */ - /** - * Log a warning at the given location. - * - * @param location Node owning the warning - * @param message Message, possibly formatted (see {@link MessageFormat}) - * @param args Arguments for the template + * Warning, classpath is misconfigured (or not configured). */ - void warning(JavaNode location, String message, Object... args); + public static final String CANNOT_RESOLVE_SYMBOL = "Cannot resolve symbol {0}"; + public static final String INACCESSIBLE_SYMBOL = "Symbol {0} is inaccessible"; + /** + * We had resolved a prefix, and a suffix is not resolved. This may + * mean that the classpath is out-of-date, or the code is incorrect. + * Eg {@code System.oute}: {@code System} is resolved, {@code oute} + * is not a member of that type. + * + *

    This differs from {@link #CANNOT_RESOLVE_SYMBOL} in that for + * the latter, it's more probable that the classpath is incorrect. + * It is emitted eg when we see an import, so a fully qualified + * name, and yet we can't resolve it. + * TODO whether it's incorrect code or incorrect classpath is only + * a guess, probably we need an option to differentiate the two + * (eg in an IDE plugin, it may well be incorrect code, but in a + * CLI run, it's more likely to be incorrect classpath). + */ + public static final String CANNOT_RESOLVE_MEMBER = "Cannot resolve ''{0}'' in {1}, treating it as {2}"; // javac gives a simple "cannot resolve symbol {0}" + /** + * TODO Should be an error. + */ + public static final String MALFORMED_GENERIC_TYPE = "Maformed generic type: expected {0} type arguments, got {1}"; + // this is an error + public static final String EXPECTED_ANNOTATION_TYPE = "Expected an annotation type"; + /** + * An ambiguous name is completely ambiguous. We don't have info + * about it at all, classpath is incomplete or code is incorrect. + * Eg {@code package.that.doesnt.exist.Type} + */ + public static final String CANNOT_RESOLVE_AMBIGUOUS_NAME = "Cannot resolve ambiguous name {0}, treating it as {1}"; + public static final String AMBIGUOUS_NAME_REFERENCE = "Reference ''{0}'' is ambiguous, both {1} and {2} match"; + private JavaSemanticErrors() { + // utility class + } - void error(JavaNode location, String message, Object... args); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/ReferenceCtx.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/ReferenceCtx.java index 166a0a6413..71fad661d2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/ReferenceCtx.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/ReferenceCtx.java @@ -4,8 +4,8 @@ package net.sourceforge.pmd.lang.java.symbols.table.internal; -import static net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger.AMBIGUOUS_NAME_REFERENCE; -import static net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger.CANNOT_RESOLVE_MEMBER; +import static net.sourceforge.pmd.lang.java.symbols.table.internal.JavaSemanticErrors.AMBIGUOUS_NAME_REFERENCE; +import static net.sourceforge.pmd.lang.java.symbols.table.internal.JavaSemanticErrors.CANNOT_RESOLVE_MEMBER; import static net.sourceforge.pmd.lang.java.types.JVariableSig.FieldSig; import java.util.HashSet; @@ -14,6 +14,7 @@ import java.util.List; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.java.ast.JavaNode; @@ -135,7 +136,7 @@ public final class ReferenceCtx { this.processor.getLogger().warning(location, CANNOT_RESOLVE_MEMBER, memberName, ownerName, fallbackStrategy); } - public SemanticChecksLogger getLogger() { + public SemanticErrorReporter getLogger() { return processor.getLogger(); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymTableFactory.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymTableFactory.java index d3be3cb313..0db3b6a9cc 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymTableFactory.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/table/internal/SymTableFactory.java @@ -22,6 +22,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.ast.NodeStream; +import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; import net.sourceforge.pmd.lang.java.ast.ASTAnyTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTFormalParameters; import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration; @@ -99,14 +100,14 @@ final class SymTableFactory { InternalApiBridge.disambigWithCtx(nodes, context); } - SemanticChecksLogger getLogger() { + SemanticErrorReporter getLogger() { return processor.getLogger(); } JClassSymbol loadClassReportFailure(JavaNode location, String fqcn) { JClassSymbol loaded = loadClassOrFail(fqcn); if (loaded == null) { - getLogger().warning(location, SemanticChecksLogger.CANNOT_RESOLVE_SYMBOL, fqcn); + getLogger().warning(location, JavaSemanticErrors.CANNOT_RESOLVE_SYMBOL, fqcn); } return loaded; @@ -118,12 +119,6 @@ final class SymTableFactory { return processor.getSymResolver().resolveClassFromCanonicalName(fqcn); } - JClassSymbol findSymbolCannotFail(String name) { - JClassSymbol found = processor.getSymResolver().resolveClassFromCanonicalName(name); - return found == null ? processor.makeUnresolvedReference(name, 0) - : found; - } - // @NonNull @@ -287,7 +282,7 @@ final class SymTableFactory { } else { // Single-Type-Import Declaration - JClassSymbol type = findSymbolCannotFail(name); + JClassSymbol type = processor.findSymbolCannotFail(name); importedTypes.append(type.getTypeSystem().typeOf(type, false)); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java index fafd311a95..a189768370 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symboltable/AbstractJavaScope.java @@ -28,7 +28,10 @@ public abstract class AbstractJavaScope extends AbstractScope { protected void checkForDuplicatedNameDeclaration(NameDeclaration declaration) { if (declaration instanceof VariableNameDeclaration && getDeclarations().keySet().contains(declaration)) { - throw new RuntimeException(declaration + " is already in the symbol table"); + // don't throw anymore + // Scopes will be removed before 7.0, and this sometimes triggers for no reason + // because Scopes were not ported to the newer grammar + // throw new RuntimeException(declaration + " is already in the symbol table"); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/JIntersectionType.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/JIntersectionType.java index f16556e684..c0ab7b8448 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/JIntersectionType.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/JIntersectionType.java @@ -14,7 +14,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.lang3.NotImplementedException; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -53,9 +52,6 @@ public final class JIntersectionType implements JTypeMirror { : "Wrong primary intersection bound: " + toString(primaryBound, allBounds); assert primaryBound != ts.OBJECT || allBounds.size() > 1 : "Intersection of a single bound: " + toString(primaryBound, allBounds); // should be caught by GLB - assert !(primaryBound instanceof JArrayType) - : "Intersection with an array is not well-formed: " - + toString(primaryBound, allBounds); // should be caught by GLB checkWellFormed(primaryBound, allBounds); @@ -95,20 +91,20 @@ public final class JIntersectionType implements JTypeMirror { /** * Every intersection type induces a notional class or interface * for the purpose of identifying its members. This may be a functional - * interface. + * interface. This returns null for the non-implemented cases. * - * @experimental currently this is only relevant to check for functional + * @experimental this is only relevant to check for functional * interface parameterization, eg {@code Runnable & Serializable}. Do * not use this to find out the members of this type, rather, use {@link #streamMethods(Predicate)} * or so. */ @Experimental - public JClassType getInducedClassType() { + public @Nullable JClassType getInducedClassType() { JTypeMirror primary = getPrimaryBound(); - if (primary instanceof JTypeVar) { + if (primary instanceof JTypeVar || primary instanceof JArrayType) { // Normally, should generate an interface which has all the members of Ti // But as per the experimental notice, this case may be ignored until needed - throw new NotImplementedException("Intersection with type variable is not implemented yet"); + return null; } if (induced == null) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/Lub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/Lub.java index d666b52f44..eb74945500 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/Lub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/Lub.java @@ -382,19 +382,6 @@ final class Lub { "Bad intersection, unrelated class types " + lastBadClass + " and " + ck + " in " + types); } - if (ck instanceof JArrayType && !bounds.isEmpty()) { - // If we get here, then the intersection looks like `A[] & B1 & .. & Bn`, - // where some Bi is not a subtype of A[], else it would have - // been pruned by mostSpecific above. Note that this means some `Bi` - // is not in { Serializable, Cloneable, Object }. Since arrays - // cannot be extended, such a bound produces an uninhabited type. - return ts.NULL_TYPE; - } else if (containsDuplicateParameterizations(bounds)) { - // assuming no two elements of the collection are subtypes of one - // another, an intersection `G & G` cannot have any instances. - return ts.NULL_TYPE; - } - if (ck == null) { if (bounds.size() == 1) { return bounds.get(0); @@ -408,19 +395,6 @@ final class Lub { return new JIntersectionType(ts, ck, bounds); } - private static boolean containsDuplicateParameterizations(List bounds) { - for (int i = 0; i < bounds.size(); i++) { - JTypeMirror bi = bounds.get(i); - for (int j = i + 1; j < bounds.size(); j++) { - JTypeMirror bj = bounds.get(j); - if (bi.getErasure().equals(bj.getErasure())) { - return true; - } - } - } - return false; - } - private static @NonNull List flattenRemoveTrivialBound(Collection types) { ArrayList bounds = new ArrayList<>(types.size()); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java index 5495db59c1..582e8ca601 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeOps.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; @@ -31,6 +30,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.internal.util.IteratorUtil; import net.sourceforge.pmd.lang.java.symbols.JClassSymbol; +import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol; import net.sourceforge.pmd.lang.java.symbols.JExecutableSymbol; import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; @@ -203,21 +203,21 @@ public final class TypeOps { return false; } - Map tMap = new HashMap<>(); - for (JTypeMirror ti : t.getInterfaces()) { - tMap.put(ti.getErasure(), ti); - } - for (JTypeMirror si : s2.getInterfaces()) { - JTypeMirror siErased = si.getErasure(); - if (!tMap.containsKey(siErased)) { - return false; + List sComps = ((JIntersectionType) s).getComponents(); + for (JTypeMirror ti : t.getComponents()) { + boolean found = false; + for (JTypeMirror si : sComps) { + // todo won't this behaves weirdly during inference? test it + if (isSameType(ti, si, inInference)) { + found = true; + break; + } } - JTypeMirror ti = tMap.remove(siErased); - if (!isSameType(ti, si, inInference)) { + if (!found) { return false; } } - return tMap.isEmpty(); + return true; } @Override @@ -661,6 +661,49 @@ public final class TypeOps { } + /** + * Generalises containment to check if for each i, {@code Ti <= Si}. + */ + static Convertibility typeArgsAreContained(JClassType t, JClassType s) { + List targs = t.getTypeArgs(); + List sargs = s.getTypeArgs(); + + if (targs.isEmpty()) { + if (sargs.isEmpty()) { + // Some "erased" non-generic types may appear as the supertypes + // of raw types, and they're different from the regular flavor + // as their own supertypes are erased, yet they're not considered + // raw. To fix the subtyping relation, we say that `C <: (erased) C` + // but `(erased) C` converts to `C` by unchecked conversion, without + // warning. + boolean tRaw = t.hasErasedSuperTypes(); + boolean sRaw = s.hasErasedSuperTypes(); + if (tRaw && !sRaw) { + return Convertibility.UNCHECKED_NO_WARNING; + } else { + return Convertibility.SUBTYPING; + } + } + // for some C, S = C<...> and T = C, ie T is raw + // T is convertible to S, by unchecked conversion. + // If S = D, then the conversion produces + // no unchecked warning. + return allArgsAreUnboundedWildcards(sargs) ? Convertibility.UNCHECKED_NO_WARNING + : Convertibility.UNCHECKED_WARNING; + } + + Convertibility result = Convertibility.SUBTYPING; + for (int i = 0; i < targs.size(); i++) { + Convertibility sub = typeArgContains(sargs.get(i), targs.get(i)); + if (sub == Convertibility.NEVER) { + return Convertibility.NEVER; + } + result = result.and(sub); + } + + return result; + } + private static final class SubtypeVisitor implements JTypeVisitor { static final SubtypeVisitor INSTANCE = new SubtypeVisitor(); @@ -725,50 +768,10 @@ public final class TypeOps { // a raw type C is a supertype for all the family of parameterized type generated by C return Convertibility.SUBTYPING; } else { - return typeArgsAreContained(superDecl, cs, superDecl.getTypeArgs(), cs.getTypeArgs()); + return typeArgsAreContained(superDecl, cs); } } - /** - * Generalises equality to check if for each i, {@code Ti <= Si}. - */ - private Convertibility typeArgsAreContained(JClassType t, JClassType s, List targs, List sargs) { - if (targs.isEmpty()) { - if (sargs.isEmpty()) { - // Some "erased" non-generic types may appear as the supertypes - // of raw types, and they're different from the regular flavor - // as their own supertypes are erased, yet they're not considered - // raw. To fix the subtyping relation, we say that `C <: (erased) C` - // but `(erased) C` converts to `C` by unchecked conversion, without - // warning. - boolean tRaw = t.hasErasedSuperTypes(); - boolean sRaw = s.hasErasedSuperTypes(); - if (tRaw && !sRaw) { - return Convertibility.UNCHECKED_NO_WARNING; - } else { - return Convertibility.SUBTYPING; - } - } - // for some C, S = C<...> and T = C, ie T is raw - // T is convertible to S, by unchecked conversion. - // If S = D, then the conversion produces - // no unchecked warning. - return allArgsAreUnboundedWildcards(sargs) ? Convertibility.UNCHECKED_NO_WARNING - : Convertibility.UNCHECKED_WARNING; - } - - Convertibility result = Convertibility.SUBTYPING; - for (int i = 0; i < targs.size(); i++) { - Convertibility sub = typeArgContains(sargs.get(i), targs.get(i)); - if (sub == Convertibility.NEVER) { - return Convertibility.NEVER; - } - result = result.and(sub); - } - - return result; - } - @Override public Convertibility visitIntersection(JIntersectionType t, JTypeMirror s) { // A & B <: A @@ -1208,33 +1211,12 @@ public final class TypeOps { * m1 is a subsignature of m2 or m2 is a subsignature of m1. This does * not look at the origin of the methods (their declaring class). * - * https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.2 + *

    This is a prerequisite for one method to override the other, + * but not the only condition. See {@link #overrides(JMethodSig, JMethodSig, JTypeMirror)}. + * + * See JLS§8 */ public static boolean areOverrideEquivalent(JMethodSig m1, JMethodSig m2) { - // This method is a very hot spot as it is used to prune shadowed/overridden/hidden - // methods from overload candidates before overload resolution. - // Any optimization makes a big impact. - if (m1.getArity() != m2.getArity()) { - return false; // easy case - } else if (m1 == m2) { - return true; - } - // Two methods can only have the same signature if they have the same type parameters - // But a generic method is allowed to override a non-generic one, and vice versa - // So we first project both methods into a form that has the same number of type parameters - boolean m1Gen = m1.isGeneric(); - boolean m2Gen = m2.isGeneric(); - if (m1Gen ^ m2Gen) { - if (m1Gen) { - m1 = m1.getErasure(); - } else { - m2 = m2.getErasure(); - } - } - return haveSameSignature(m1, m2); - } - - public static boolean areOverrideEquivalentFast(JMethodSig m1, JMethodSig m2) { // This method is a very hot spot as it is used to prune shadowed/overridden/hidden // methods from overload candidates before overload resolution. // Any optimization makes a big impact. @@ -1243,6 +1225,8 @@ public final class TypeOps { } else if (m1 == m2) { return true; } else if (!m1.getName().equals(m2.getName())) { + // note: most call sites statically know this is true + // profile to figure out whether this matters return false; } @@ -1256,7 +1240,11 @@ public final class TypeOps { return false; } } - return true; + + // a non-generic method may override a generic one + return !m1.isGeneric() || !m2.isGeneric() + // if both are generic, they must have the same type params + || haveSameTypeParams(m1, m2); } /** @@ -1323,7 +1311,7 @@ public final class TypeOps { JTypeMirror m1Owner = m1.getDeclaringType(); JClassType m2Owner = (JClassType) m2.getDeclaringType(); - if (isOverridableIn(m2, m2Owner.getSymbol(), m1Owner.getSymbol())) { + if (isOverridableIn(m2, m1Owner.getSymbol())) { JClassType m2AsM1Supertype = (JClassType) m1Owner.getAsSuper(m2Owner.getSymbol()); if (m2AsM1Supertype != null) { JMethodSig m2Prime = m2AsM1Supertype.getDeclaredMethod(m2.getSymbol()); @@ -1337,7 +1325,7 @@ public final class TypeOps { // todo that is very weird if (m1.isAbstract() || !m2.isAbstract() && !m2.getSymbol().isDefaultMethod() - || !isOverridableIn(m2, m2Owner.getSymbol(), origin.getSymbol()) + || !isOverridableIn(m2, origin.getSymbol()) || !(m1Owner instanceof JClassType)) { return false; } @@ -1353,6 +1341,10 @@ public final class TypeOps { return false; } + private static boolean isOverridableIn(JMethodSig m, JTypeDeclSymbol origin) { + return isOverridableIn(m.getSymbol(), origin); + } + /** * Returns true if the given method can be overridden in the origin * class. This only checks access modifiers and not eg whether the @@ -1365,10 +1357,13 @@ public final class TypeOps { * if the method is static. * * @param m Method to test - * @param declaring Symbol of the declaring type of m * @param origin Site of the potential override */ - private static boolean isOverridableIn(JMethodSig m, JClassSymbol declaring, JTypeDeclSymbol origin) { + public static boolean isOverridableIn(JExecutableSymbol m, JTypeDeclSymbol origin) { + if (m instanceof JConstructorSymbol) { + return false; + } + final int accessFlags = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; // JLS 8.4.6.1 @@ -1380,7 +1375,7 @@ public final class TypeOps { case 0: // package private return - declaring.getPackageName().equals(origin.getPackageName()) + m.getPackageName().equals(origin.getPackageName()) && !origin.isInterface(); default: // private diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeSystem.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeSystem.java index 2c7d1d1cb1..86f6abe520 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeSystem.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeSystem.java @@ -674,7 +674,8 @@ public final class TypeSystem { * *

    If after these transformations, only a single component remains, * then that is the returned type. Otherwise a {@link JIntersectionType} - * is created. + * is created. Note that the intersection may be unsatisfiable (eg {@code A[] & Runnable}), + * but we don't attempt to minimize this to {@link #NULL_TYPE}. * *

    See also JLS§4.9 (Intersection types). * diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java index 1b48b56659..cc736366ea 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/TypeTestUtil.java @@ -4,10 +4,11 @@ package net.sourceforge.pmd.lang.java.types; +import java.lang.reflect.Modifier; + import org.apache.commons.lang3.StringUtils; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.objectweb.asm.Opcodes; import net.sourceforge.pmd.internal.util.AssertionUtil; import net.sourceforge.pmd.lang.java.ast.TypeNode; @@ -31,14 +32,17 @@ public final class TypeTestUtil { * if the type of the node is parameterized. Examples: * *

    {@code
    -     * isA(()>, List.class)      = true
    -     * isA(()>, ArrayList.class) = true
    -     * isA(, int[].class)                  = true
    -     * isA(, Object[].class)            = true
    +     * isA(List.class, ()>)      = true
    +     * isA(ArrayList.class, ()>) = true
    +     * isA(int[].class, )                  = true
    +     * isA(Object[].class, )            = true
          * isA(_, null) = false
          * isA(null, _) = NullPointerException
          * }
    * + *

    If either type is unresolved, the types are tested for equality, + * thus giving more useful results than {@link JTypeMirror#isSubtypeOf(JTypeMirror)}. + * * @param clazz a class (non-null) * @param node the type node to check * @@ -47,15 +51,31 @@ public final class TypeTestUtil { * @throws NullPointerException if the class parameter is null */ public static boolean isA(final @NonNull Class clazz, final @Nullable TypeNode node) { - AssertionUtil.requireParamNotNull("class", (Object) clazz); + AssertionUtil.requireParamNotNull("class", clazz); if (node == null) { return false; - } else if (node.getType() == clazz) { - return true; } - return canBeExtended(clazz) ? isA(clazz.getName(), node) - : isExactlyA(clazz, node); + return hasNoSubtypes(clazz) ? isExactlyA(clazz, node) + : isA(clazz, node.getTypeMirror()); + } + + + private static boolean isA(@NonNull Class clazz, @Nullable JTypeMirror type) { + AssertionUtil.requireParamNotNull("klass", clazz); + if (type == null) { + return false; + } + + JTypeMirror otherType = TypesFromReflection.fromReflect(clazz, type.getTypeSystem()); + + if (otherType == null || TypeOps.isUnresolved(type)) { + // We'll return true if the types have equal symbols (same binary name), + // but we ignore subtyping. + return isExactlyA(clazz, type.getSymbol()); + } + + return type.isSubtypeOf(otherType); } @@ -65,10 +85,10 @@ public final class TypeTestUtil { * if the type of the node is parameterized. Examples: * *

    {@code
    -     * isA(()>, "java.util.List")      = true
    -     * isA(()>, "java.util.ArrayList") = true
    -     * isA(, "int[]")                            = true
    -     * isA(, "java.lang.Object[]")            = true
    +     * isA("java.util.List", ()>)      = true
    +     * isA("java.util.ArrayList", ()>) = true
    +     * isA("int[]", )                            = true
    +     * isA("java.lang.Object[]", )            = true
          * isA(_, null) = false
          * isA(null, _) = NullPointerException
          * }
    @@ -96,6 +116,7 @@ public final class TypeTestUtil { if (thisClass != null && thisClass.isUnresolved()) { // we can't get any useful info from this, isSubtypeOf would return true + // do not test for equality, we already checked isExactlyA, which has its fallback return false; } @@ -137,17 +158,30 @@ public final class TypeTestUtil { * @throws NullPointerException if the class parameter is null */ public static boolean isExactlyA(final @NonNull Class clazz, final @Nullable TypeNode node) { - AssertionUtil.requireParamNotNull("class", (Object) clazz); + AssertionUtil.requireParamNotNull("class", clazz); if (node == null) { return false; } - JTypeDeclSymbol sym = node.getTypeMirror().getSymbol(); - if (sym == null || sym instanceof JTypeParameterSymbol) { + return isExactlyA(clazz, node.getTypeMirror().getSymbol()); + } + + private static boolean isExactlyA(@NonNull Class klass, @Nullable JTypeDeclSymbol type) { + AssertionUtil.requireParamNotNull("klass", klass); + if (!(type instanceof JClassSymbol)) { + // Class cannot reference a type parameter return false; } - return ((JClassSymbol) sym).getBinaryName().equals(clazz.getName()); + JClassSymbol symClass = (JClassSymbol) type; + + if (klass.isArray()) { + return symClass.isArray() && isExactlyA(klass.getComponentType(), symClass.getArrayComponent()); + } + + // Note: klass.getName returns a type descriptor for arrays, + // which is why we have to destructure the array above + return symClass.getBinaryName().equals(klass.getName()); } @@ -157,10 +191,10 @@ public final class TypeTestUtil { * if the type of the node is parameterized. * *
    {@code
    -     * isExactlyA(()>, List.class)      = false
    -     * isExactlyA(()>, ArrayList.class) = true
    -     * isExactlyA(, int[].class)                  = true
    -     * isExactlyA(, Object[].class)            = false
    +     * isExactlyA(List.class, ()>)      = false
    +     * isExactlyA(ArrayList.class, ()>) = true
    +     * isExactlyA(int[].class, )                  = true
    +     * isExactlyA(Object[].class, )            = false
          * isExactlyA(_, null) = false
          * isExactlyA(null, _) = NullPointerException
          * }
    @@ -191,9 +225,12 @@ public final class TypeTestUtil { } - private static boolean canBeExtended(Class clazz) { + + private static boolean hasNoSubtypes(Class clazz) { // Neither final nor an annotation. Enums & records have ACC_FINAL - return (clazz.getModifiers() & (Opcodes.ACC_ANNOTATION | Opcodes.ACC_FINAL)) == 0; + // Note: arrays have ACC_FINAL, but have subtypes by covariance + // Note: annotations may be implemented by classes + return Modifier.isFinal(clazz.getModifiers()) && !clazz.isArray(); } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/OverloadSet.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/OverloadSet.java index 12791e1d30..640c016599 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/OverloadSet.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/OverloadSet.java @@ -5,7 +5,7 @@ package net.sourceforge.pmd.lang.java.types.internal.infer; -import static net.sourceforge.pmd.lang.java.types.TypeOps.areOverrideEquivalentFast; +import static net.sourceforge.pmd.lang.java.types.TypeOps.areOverrideEquivalent; import static net.sourceforge.pmd.util.OptionalBool.NO; import static net.sourceforge.pmd.util.OptionalBool.UNKNOWN; import static net.sourceforge.pmd.util.OptionalBool.YES; @@ -107,7 +107,7 @@ public abstract class OverloadSet { @Override protected OptionalBool shouldTakePrecedence(JMethodSig m1, JMethodSig m2) { - return areOverrideEquivalentFast(m1, m2) + return areOverrideEquivalent(m1, m2) ? shouldAlwaysTakePrecedence(m1, m2, viewingSite) : OptionalBool.UNKNOWN; } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java index f88d225a52..7b35d8fee2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java @@ -18,7 +18,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.JavaNode; -import net.sourceforge.pmd.lang.java.rule.security.TypeResTestRule; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.java.types.JMethodSig; import net.sourceforge.pmd.lang.java.types.JTypeMirror; @@ -287,9 +286,7 @@ public interface TypeInferenceLogger { } private String fileLocation(ExprMirror mirror) { - JavaNode node = mirror.getLocation(); - return TypeResTestRule.FILENAME.get() + ":" + node.getBeginLine() + " :" + node.getBeginColumn() + ".." - + node.getEndLine() + ":" + node.getEndColumn(); + return mirror.getLocation().getReportLocation().startPosToStringWithFile(); } protected @NonNull String ppMethod(JMethodSig sig) { diff --git a/pmd-java/src/main/resources/category/java/design.xml b/pmd-java/src/main/resources/category/java/design.xml index 7968b6ec57..8b743427ae 100644 --- a/pmd-java/src/main/resources/category/java/design.xml +++ b/pmd-java/src/main/resources/category/java/design.xml @@ -411,11 +411,11 @@ public class Foo { private Bar var2; //followed by many imports of unique objects - void ObjectC doWork() { + ObjectC doWork() { Bardo var55; ObjectA var44; ObjectZ var93; - return something; + return something(); } } ]]> @@ -616,7 +616,7 @@ user-specified threshold. @@ -132,7 +133,7 @@ empty methods. diff --git a/pmd-java/src/main/resources/category/java/errorprone.xml b/pmd-java/src/main/resources/category/java/errorprone.xml index de67364d10..5121280ffc 100644 --- a/pmd-java/src/main/resources/category/java/errorprone.xml +++ b/pmd-java/src/main/resources/category/java/errorprone.xml @@ -1248,42 +1248,6 @@ public class GCCall { - - -Web applications should not call System.exit(), since only the web container or the -application server should stop the JVM. This rule also checks for the equivalent call Runtime.getRuntime().exit(). - - 3 - - - - - - - - - - - - + + +Web applications should not call `System.exit()`, since only the web container or the +application server should stop the JVM. Otherwise a web application would terminate all other applications +running on the same application server. + +This rule also checks for the equivalent calls `Runtime.getRuntime().exit()` and `Runtime.getRuntime().halt()`. + +This rule was called *DoNotCallSystemExit* until PMD 6.29.0. + + 3 + + + + + + + + + + + + - + diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java index 563e925ef1..80424834d3 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/ExcludeLinesTest.java @@ -4,39 +4,45 @@ package net.sourceforge.pmd; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertSize; +import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertSuppressed; -import org.junit.Before; import org.junit.Test; import net.sourceforge.pmd.lang.ParserOptions; -import net.sourceforge.pmd.lang.java.JavaParsingHelper; -import net.sourceforge.pmd.testframework.RuleTst; -import net.sourceforge.pmd.testframework.TestDescriptor; +import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId; +import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule; +import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; -public class ExcludeLinesTest extends RuleTst { - private Rule rule; - - @Before - public void setUp() { - rule = findRule("java-unusedcode", "UnusedLocalVariable"); - } +public class ExcludeLinesTest extends BaseNonParserTest { @Test public void testAcceptance() { - runTest(new TestDescriptor(TEST1, "NOPMD should work", 0, rule)); - runTest(new TestDescriptor(TEST2, "Should fail without exclude marker", 1, rule)); + assertSize(java.executeRule(getRule(), TEST1), 0); + assertSize(java.executeRule(getRule(), TEST2), 1); + } + + public Rule getRule() { + return new AbstractJavaRule() { + { + setMessage("!"); + } + + @Override + public Object visit(ASTVariableDeclaratorId node, Object data) { + addViolation(data, node); + return data; + } + }; } @Test public void testAlternateMarker() { - - Report r = JavaParsingHelper.WITH_PROCESSING.withParserOptions(new ParserOptions("FOOBAR")) - .executeRule(rule, TEST3); - - assertTrue(r.getViolations().isEmpty()); - assertEquals(r.getSuppressedViolations().size(), 1); + ParserOptions options = new ParserOptions(); + options.setSuppressMarker("FOOBAR"); + Report rpt = java.withParserOptions(options).executeRule(getRule(), TEST3); + assertSize(rpt, 0); + assertSuppressed(rpt, 1); } private static final String TEST1 = "public class Foo {" + PMD.EOL + " void foo() {" + PMD.EOL + " int x; //NOPMD " diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/coverage/PMDCoverageTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/coverage/PMDCoverageTest.java index a8b4a8ef5f..71609c599d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/coverage/PMDCoverageTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/coverage/PMDCoverageTest.java @@ -8,11 +8,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.fail; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import org.apache.commons.io.FileUtils; @@ -21,6 +18,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardErrorStreamLog; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; +import org.junit.rules.TemporaryFolder; import net.sourceforge.pmd.PMD; @@ -32,6 +30,9 @@ public class PMDCoverageTest { @Rule public StandardErrorStreamLog errorStream = new StandardErrorStreamLog(); + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + /** * Test some of the PMD command line options */ @@ -49,9 +50,8 @@ public class PMDCoverageTest { String[] args; args = commandLine.split("\\s"); - File f = null; try { - f = File.createTempFile("pmd", ".txt"); + File f = folder.newFile(); int n = args.length; String[] a = new String[n + 2 + 2]; System.arraycopy(args, 0, a, 0, n); @@ -77,44 +77,11 @@ public class PMDCoverageTest { assertEquals("No parsing error expected", 0, StringUtils.countMatches(report, "Error while parsing")); } catch (IOException ioe) { fail("Problem creating temporary file: " + ioe.getLocalizedMessage()); - } finally { - if (f != null) { - f.delete(); - } } } - /** - * Name of the configuration file used by testResourceFileCommands(). - */ - private static final String PMD_CONFIG_FILE = "pmd_tests.conf"; - - /** - * Run PMD using the command lines found in PMD_CONFIG_FILE. - */ @Test - public void testResourceFileCommands() { - - InputStream is = getClass().getResourceAsStream(PMD_CONFIG_FILE); - - if (is != null) { - try { - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - String l; - while ((l = r.readLine()) != null) { - l = l.trim(); - if (l.length() == 0 || l.charAt(0) == '#') { - continue; - } - - runPmd(l); - } - r.close(); - } catch (IOException ioe) { - fail("Problem reading config file: " + ioe.getLocalizedMessage()); - } - } else { - fail("Missing config file: " + PMD_CONFIG_FILE); - } + public void runAllJavaPmdOnSourceTree() { + runPmd("-d src/main/java -f text -R rulesets/internal/all-java.xml -language java"); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaParsingHelper.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaParsingHelper.java index f87b22756f..b0537a9fa8 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaParsingHelper.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/JavaParsingHelper.java @@ -5,7 +5,6 @@ package net.sourceforge.pmd.lang.java; import java.io.PrintStream; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -18,11 +17,12 @@ import org.jetbrains.annotations.NotNull; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.LanguageVersionHandler; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.SemanticErrorReporter; +import net.sourceforge.pmd.lang.ast.SemanticException; import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.JavaNode; import net.sourceforge.pmd.lang.java.internal.JavaAstProcessor; -import net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger; import net.sourceforge.pmd.lang.java.types.TypeSystem; import net.sourceforge.pmd.lang.java.types.internal.infer.TypeInferenceLogger; import net.sourceforge.pmd.lang.java.types.internal.infer.TypeInferenceLogger.SimpleLogger; @@ -40,15 +40,16 @@ public class JavaParsingHelper extends BaseParsingHelper>> warnings = new HashMap<>(); + public final Map>> errors = new HashMap<>(); - @Override - public void warning(JavaNode location, String message, Object... args) { - - } - - @Override - public void error(JavaNode location, String message, Object... args) { - - } - } - - public static class TestCheckLogger implements SemanticChecksLogger { - - private static final Logger LOG = Logger.getLogger(TestCheckLogger.class.getName()); - public final Map>> warnings = new HashMap<>(); - public final Map>> errors = new HashMap<>(); - - private final boolean doLogOnConsole; + private final SemanticErrorReporter baseLogger; public TestCheckLogger() { this(false); } public TestCheckLogger(boolean doLogOnConsole) { - this.doLogOnConsole = doLogOnConsole; + Logger consoleLogger = Logger.getAnonymousLogger(); + if (!doLogOnConsole) { + consoleLogger.setLevel(Level.OFF); + } + baseLogger = SemanticErrorReporter.reportToLogger(consoleLogger); } @Override - public void warning(JavaNode location, String message, Object... args) { - log(location, message, args, Level.WARNING); + public void warning(Node location, String message, Object... args) { warnings.computeIfAbsent(message, k -> new ArrayList<>()) .add(new Pair<>(location, args)); + + baseLogger.warning(location, message, args); } @Override - public void error(JavaNode location, String message, Object... args) { - log(location, message, args, Level.SEVERE); + public SemanticException error(Node location, String message, Object... args) { errors.computeIfAbsent(message, k -> new ArrayList<>()) .add(new Pair<>(location, args)); + return baseLogger.error(location, message, args); } - - public void log(JavaNode location, String message, Object[] args, Level level) { - if (doLogOnConsole) { - LOG.log(level, formatLoc(location) + new MessageFormat(message).format(args)); - } + @Override + public boolean hasError() { + return baseLogger.hasError(); } - - @NonNull - private String formatLoc(JavaNode location) { - return "[" + location.getBeginLine() + "," + location.getBeginColumn() + "] "; - } - } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java index 3401199005..d4406a6ed0 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/PMD5RulesetTest.java @@ -7,16 +7,15 @@ package net.sourceforge.pmd.lang.java; import org.junit.Assert; import org.junit.Test; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; -import net.sourceforge.pmd.util.ResourceLoader; +import net.sourceforge.pmd.RuleSetParser; public class PMD5RulesetTest { @Test public void loadRuleset() throws Exception { - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, true); + RuleSetFactory ruleSetFactory = new RuleSetParser().toFactory(); RuleSet ruleset = ruleSetFactory.createRuleSet("net/sourceforge/pmd/lang/java/pmd5ruleset.xml"); Assert.assertNotNull(ruleset); Assert.assertNull(ruleset.getRuleByName("GuardLogStatementJavaUtil")); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java index 816c98b918..36aeb6d81f 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/QuickstartRulesetTest.java @@ -14,11 +14,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; -import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; -import net.sourceforge.pmd.util.ResourceLoader; +import net.sourceforge.pmd.RuleSetParser; public class QuickstartRulesetTest { @@ -50,8 +49,7 @@ public class QuickstartRulesetTest { } }); - RuleSetFactory ruleSetFactory = new RuleSetFactory(new ResourceLoader(), RulePriority.LOW, true, false); - RuleSet quickstart = ruleSetFactory.createRuleSet("rulesets/java/quickstart.xml"); + RuleSet quickstart = new RuleSetParser().enableCompatibility(false).parseFromResource("rulesets/java/quickstart.xml"); Assert.assertFalse(quickstart.getRules().isEmpty()); } } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentTest.java new file mode 100644 index 0000000000..e81f8e9934 --- /dev/null +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentAssignmentTest.java @@ -0,0 +1,129 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; + +public class CommentAssignmentTest extends BaseNonParserTest { + + /** + * Blank lines in comments should not raise an exception. See bug #1048. + */ + @Test + public void testFilteredCommentIn() { + ASTCompilationUnit node = java.parse("public class Foo {\n" + + " /* multi line comment with blank lines\n\n\n */\n" + + " /** a formal comment with blank lines\n\n\n */" + + "}"); + + Comment comment = node.getComments().get(0); + + assertThat(comment, instanceOf(MultiLineComment.class)); + assertEquals("multi line comment with blank lines", comment.getFilteredComment()); + + comment = node.getComments().get(1); + assertThat(comment, instanceOf(FormalComment.class)); + assertEquals("a formal comment with blank lines", comment.getFilteredComment()); + } + + + @Test + public void testCommentAssignments() { + + ASTCompilationUnit node = java.parse("public class Foo {\n" + + " /** Comment 1 */\n" + + " public void method1() {}\n" + + " \n" + + " /** Comment 2 */\n" + + " \n" + + " /** Comment 3 */\n" + + " public void method2() {}" + "}"); + + List methods = node.findDescendantsOfType(ASTMethodDeclaration.class); + assertCommentEquals(methods.get(0), "/** Comment 1 */"); + assertCommentEquals(methods.get(1), "/** Comment 3 */"); + } + + @Test + public void testCommentAssignmentsWithAnnotation() { + + ASTCompilationUnit node = java.parse("public class Foo {\n" + + " /** Comment 1 */\n" + + " @Oha public void method1() {}\n" + + " \n" + + " /** Comment 2 */\n" + + " @Oha\n" + // note that since this is the first token, the prev comment gets selected + + " /** Comment 3 */\n" + + " public void method2() {}" + "}"); + + List methods = node.findDescendantsOfType(ASTMethodDeclaration.class); + assertCommentEquals(methods.get(0), "/** Comment 1 */"); + assertCommentEquals(methods.get(1), "/** Comment 2 */"); + } + + @Test + public void testCommentAssignmentOnPackage() { + + ASTCompilationUnit node = java.parse("/** Comment 1 */\n" + + "package bar;\n"); + + assertCommentEquals(node.descendants(ASTPackageDeclaration.class).firstOrThrow(), + "/** Comment 1 */"); + } + + @Test + public void testCommentAssignmentOnClass() { + + ASTCompilationUnit node = java.parse("/** outer */\n" + + "class Foo { " + + " /** inner */ class Nested { } " + + " { /** local */ class Local {}} " + + " /** enum */enum NestedEnum {}" + + "}"); + + List types = node.descendants(ASTAnyTypeDeclaration.class).toList(); + assertCommentEquals(types.get(0), "/** outer */"); + assertCommentEquals(types.get(1), "/** inner */"); + assertCommentEquals(types.get(2), "/** local */"); + assertCommentEquals(types.get(3), "/** enum */"); + } + + @Test + public void testCommentAssignmentOnEnum() { + + ASTCompilationUnit node = java.parse("enum Foo { " + + " /** A */ A," + + " /** B */ @Oha B," + + " C," + + " /* not javadoc */ D," + + "}"); + + List constants = node.descendants(ASTEnumConstant.class).toList(); + assertCommentEquals(constants.get(0), "/** A */"); + assertCommentEquals(constants.get(1), "/** B */"); + assertHasNoComment(constants.get(2)); + assertHasNoComment(constants.get(3)); + } + + + private void assertCommentEquals(JavadocCommentOwner pack, String expected) { + Assert.assertNotNull("null comment on " + pack, pack.getJavadocComment()); + Assert.assertEquals(expected, pack.getJavadocComment().getText().toString()); + } + + private void assertHasNoComment(JavadocCommentOwner pack) { + Assert.assertNull("Expected null comment on " + pack, pack.getJavadocComment()); + } +} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentTest.java index c04e3c0c85..70e381897e 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentTest.java @@ -9,9 +9,9 @@ import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; +import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; -public class CommentTest { +public class CommentTest extends BaseNonParserTest { @Test public void testMultiLinesInSingleLine() { String comment = "/* single line. */"; @@ -98,14 +98,7 @@ public class CommentTest { } private String filter(String comment) { - JavaccToken t = new JavaccToken(comment); - Comment node = new Comment(t) { - @Override - public String getXPathNodeName() { - return "DummyComment"; - } - }; - return node.getFilteredComment(); + return java.parse(comment).getComments().get(0).getFilteredComment(); } private int lineCount(String filtered) { diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentUtilTest.java deleted file mode 100644 index b6b50c5aa7..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/CommentUtilTest.java +++ /dev/null @@ -1,238 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.ast; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - - -public class CommentUtilTest { - - @Test - public void testFindJavaDocTags() { - String formalComment = - "/**\n" - + " * @see something\n" - + " * @author Author1\n" - + " * @author Author2\n" - + " * @param parm1 description\n" - + " */\n"; - - Map javadocTagsIn = CommentUtil.javadocTagsIn(formalComment); - Assert.assertEquals(3, javadocTagsIn.size()); - Assert.assertEquals(7, javadocTagsIn.get("see").intValue()); - Assert.assertEquals("@see", formalComment.substring(7, 7 + 4)); - Assert.assertEquals("@author", formalComment.substring(javadocTagsIn.get("author"), - javadocTagsIn.get("author") + "author".length() + 1)); - } - - @Test - public void testFindJavaDocTagsEmpty() { - Map javadocTagsIn = CommentUtil.javadocTagsIn(""); - Assert.assertEquals(0, javadocTagsIn.size()); - } - - @Test - public void testFindJavaDocTagsNull() { - Map javadocTagsIn = CommentUtil.javadocTagsIn(null); - Assert.assertEquals(0, javadocTagsIn.size()); - } - - @Test - public void testMultiLinesInSingleLine() { - String comment = "/* single line. */"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(1, lines.size()); - Assert.assertEquals("single line.", lines.get(0)); - } - - @Test - public void testMultiLinesInSingleLineSimple() { - String comment = "// single line."; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(1, lines.size()); - Assert.assertEquals("single line.", lines.get(0)); - } - - @Test - public void testMultiLinesInSingleLineFormal() { - String comment = "/** single line. */"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(1, lines.size()); - Assert.assertEquals("single line.", lines.get(0)); - } - - @Test - public void testMultiLinesInMultiLine() { - String comment = - "/*\n" - + " * line 1\n" - + " * line 2\n" - + " */\n"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(2, lines.size()); - Assert.assertEquals("line 1", lines.get(0)); - Assert.assertEquals("line 2", lines.get(1)); - } - - @Test - public void testMultiLinesInMultiLineCrLf() { - String comment = - "/*\r\n" - + " * line 1\r\n" - + " * line 2\r\n" - + " */\r\n"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(2, lines.size()); - Assert.assertEquals("line 1", lines.get(0)); - Assert.assertEquals("line 2", lines.get(1)); - } - - @Test - public void testMultiLinesInMultiLineFormal() { - String comment = - "/**\n" - + " * line 1\n" - + " * line 2\n" - + " */\n"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(2, lines.size()); - Assert.assertEquals("line 1", lines.get(0)); - Assert.assertEquals("line 2", lines.get(1)); - } - - @Test - public void testMultiLinesInMultiLineFormalCrLf() { - String comment = - "/**\r\n" - + " * line 1\r\n" - + " * line 2\r\n" - + " */\r\n"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(2, lines.size()); - Assert.assertEquals("line 1", lines.get(0)); - Assert.assertEquals("line 2", lines.get(1)); - } - - @Test - public void testMultiLinesInMultiLineNoAsteriskEmpty() { - String comment = - "/**\n" - + " * line 1\n" - + "line 2\n" - + "\n" - + " */\n"; - List lines = CommentUtil.multiLinesIn(comment); - Assert.assertEquals(2, lines.size()); - Assert.assertEquals("line 1", lines.get(0)); - Assert.assertEquals("line 2", lines.get(1)); - } - - @Test - public void testTrim() { - List lines = Arrays.asList("", "a", "", ""); - List trimmed = CommentUtil.trim(lines); - Assert.assertEquals(1, trimmed.size()); - Assert.assertEquals("a", trimmed.get(0)); - } - - @Test - public void testTrimNotMiddle() { - List lines = Arrays.asList("a", "b", "", "c"); - List trimmed = CommentUtil.trim(lines); - Assert.assertEquals(4, trimmed.size()); - Assert.assertEquals("a", trimmed.get(0)); - Assert.assertEquals("b", trimmed.get(1)); - Assert.assertEquals("", trimmed.get(2)); - Assert.assertEquals("c", trimmed.get(3)); - } - - @Test - public void testTrimEmpty() { - List trimmed = CommentUtil.trim(new ArrayList()); - Assert.assertEquals(0, trimmed.size()); - } - - @Test - public void testTrimNull() { - List trimmed = CommentUtil.trim(null); - Assert.assertEquals(0, trimmed.size()); - } - - @Test - public void testWordAfter() { - String wordAfter = CommentUtil.wordAfter("@param param1 Description", "@param".length()); - Assert.assertEquals("param1", wordAfter); - } - - @Test - public void testWordAfterPositionOutOfBounds() { - String wordAfter = CommentUtil.wordAfter("@param param1 Description", Integer.MAX_VALUE); - Assert.assertNull(wordAfter); - } - - @Test - public void testWordAfterNull() { - String wordAfter = CommentUtil.wordAfter(null, 0); - Assert.assertNull(wordAfter); - } - - @Test - public void testJavadocAfter() { - String javadocContentAfter = CommentUtil.javadocContentAfter("@param param1 The Description\n", - "@param param1".length()); - Assert.assertEquals("The Description", javadocContentAfter); - } - - @Test - public void testJavadocAfterOutOfBounds() { - String javadocContentAfter = CommentUtil.javadocContentAfter("@param param1 The Description\n", - Integer.MAX_VALUE); - Assert.assertNull(javadocContentAfter); - } - - @Test - public void testJavadocAfterNull() { - String javadocContentAfter = CommentUtil.javadocContentAfter(null, 0); - Assert.assertNull(javadocContentAfter); - } - - @Test - public void testJavadoc() { - String comment = " /**\n" - + " * Checks if the metric can be computed on the node.\n" - + " *\n" - + " * @param node The node to check\n" - + " *\n" - + " * @return True if the metric can be computed\n" - + " */\n" - + " boolean supports(N node);\n" - + ""; - List lines = CommentUtil.multiLinesIn(comment); - lines = CommentUtil.trim(lines); - - for (String line : lines) { - Map tags = CommentUtil.javadocTagsIn(line); - for (String tag : tags.keySet()) { - int pos = tags.get(tag) + tag.length() + 1; - String wordAfter = CommentUtil.wordAfter(line, pos); - pos = pos + wordAfter.length() + 1; - String description = CommentUtil.javadocContentAfter(line, pos); - if ("param".equals(tag)) { - Assert.assertEquals("node", wordAfter); // the parameter name - Assert.assertEquals("The node to check", description); - } else if ("return".equals(tag)) { - Assert.assertEquals("True", wordAfter); - Assert.assertEquals("if the metric can be computed", description); - } - } - } - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/FormalCommentTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/FormalCommentTest.java index 9c6abefeca..5c8f8b11da 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/FormalCommentTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/ast/FormalCommentTest.java @@ -4,16 +4,20 @@ package net.sourceforge.pmd.lang.java.ast; +import static org.junit.Assert.assertEquals; + import org.junit.Assert; import org.junit.Test; import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; -public class FormalCommentTest { +public class FormalCommentTest extends BaseParserTest { @Test public void testJavadocTagsAsChildren() { - String comment = " /**\n" + ASTCompilationUnit acu = java.parse( + "interface Metric {" + + " /**\n" + " * Checks if the metric can be computed on the node.\n" + " *\n" + " * @param node The node to check\n" @@ -21,10 +25,20 @@ public class FormalCommentTest { + " * @return True if the metric can be computed\n" + " */\n" + " boolean supports(N node);\n" - + ""; + + "}"); - JavaccToken token = new JavaccToken(comment); - FormalComment commentNode = new FormalComment(token); + ASTType booleanT = acu.descendants(ASTType.class).firstOrThrow(); + JavaccToken firstToken = booleanT.getFirstToken(); + assertEquals("Boolean", JavaTokenKinds.BOOLEAN, firstToken.kind); + JavaccToken comment = firstToken.getPreviousComment(); + assertEquals("Implicit modifier list", JavaccToken.IMPLICIT_TOKEN, comment.kind); + comment = comment.getPreviousComment(); + assertEquals("Whitespace", JavaTokenKinds.WHITESPACE, comment.kind); + assertEquals("\n ", comment.getImage()); + comment = comment.getPreviousComment(); + assertEquals("Formal comment", JavaTokenKinds.FORMAL_COMMENT, comment.kind); + + FormalComment commentNode = new FormalComment(comment); Assert.assertEquals(2, commentNode.getNumChildren()); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java index 385a688ffd..494d91ffdb 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/JavaRuleViolationTest.java @@ -59,7 +59,7 @@ public class JavaRuleViolationTest { @NonNull public RuleViolation violationAt(JavaNode md) { - return new JavaRuleViolation(new FooRule(), md, "", ""); + return new JavaRuleViolation(new FooRule(), md, ""); } /** diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java index cdf772c594..8dd80c83fb 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/XPathRuleTest.java @@ -9,7 +9,6 @@ import static org.junit.Assert.assertEquals; import java.util.HashMap; import java.util.List; -import org.junit.Ignore; import org.junit.Test; import net.sourceforge.pmd.PMD; @@ -101,32 +100,6 @@ public class XPathRuleTest extends RuleTst { } - /** - * Test for problem reported in bug #1219 PrimarySuffix/@Image does not work - * in some cases in xpath 2.0 - * - * @throws Exception - * any error - */ - @Test - @Ignore("Primary suffix has been removed") - public void testImageOfPrimarySuffix() throws Exception { - final String SUFFIX = "import java.io.File;\n" + "\n" + "public class TestSuffix {\n" - + " public static void main(String args[]) {\n" + " new File(\"subdirectory\").list();\n" - + " }\n" + "}"; - ASTCompilationUnit cu = JavaParsingHelper.WITH_PROCESSING.parse(SUFFIX); - - String xpath = "//PrimarySuffix[@Image='list']"; - - SaxonXPathRuleQuery xpathRuleQuery = new SaxonXPathRuleQuery(xpath, - XPathVersion.DEFAULT, - new HashMap<>(), - XPathHandler.noFunctionDefinitions(), - DeprecatedAttrLogger.noop()); - List nodes = xpathRuleQuery.evaluate(cu); - assertEquals(1, nodes.size()); - } - /** * Following sibling check: See https://sourceforge.net/p/pmd/bugs/1209/ * diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideTest.java index 41a94483a4..edd71d4de3 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/MissingOverrideTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class MissingOverrideTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentTest.java index c58ac7709c..7d363ef084 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/bestpractices/UnusedAssignmentTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.bestpractices; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class UnusedAssignmentTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRuleTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRuleTest.java deleted file mode 100644 index 953c85cd8a..0000000000 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/AbstractCommentRuleTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.lang.java.rule.documentation; - -import static org.junit.Assert.assertEquals; - -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; - -import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken; -import net.sourceforge.pmd.lang.java.JavaParsingHelper; -import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; -import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration; -import net.sourceforge.pmd.lang.java.ast.FormalComment; -import net.sourceforge.pmd.lang.java.ast.MultiLineComment; - -public class AbstractCommentRuleTest { - - private AbstractCommentRule testSubject = new AbstractCommentRule() { - }; - - /** - * Blank lines in comments should not raise an exception. See bug #1048. - */ - @Test - public void testFilteredCommentIn() { - JavaccToken token = new JavaccToken("/* multi line comment with blank lines\n\n\n */"); - - String filtered = testSubject.filteredCommentIn(new MultiLineComment(token)); - assertEquals("multi line comment with blank lines", filtered); - - token = new JavaccToken("/** a formal comment with blank lines\n\n\n */"); - filtered = testSubject.filteredCommentIn(new FormalComment(token)); - assertEquals("a formal comment with blank lines", filtered); - } - - @Test - public void testTagsIndicesIn() { - String comment = " /**\n" - + " * Checks if the metric can be computed on the node.\n" - + " *\n" - + " * @param node The node to check\n" - + " *\n" - + " * @return True if the metric can be computed\n" - + " */\n" - + " boolean supports(N node);\n" - + ""; - - List indices = testSubject.tagsIndicesIn(comment); - Assert.assertEquals(2, indices.size()); - Assert.assertEquals(79, indices.get(0).intValue()); - Assert.assertEquals(123, indices.get(1).intValue()); - } - - @Test - public void testCommentAssignments() { - ASTCompilationUnit node = JavaParsingHelper.WITH_PROCESSING.parse("public class Foo {" + " /** Comment 1 */\n" - + " public void method1() {}\n" + " \n" + " /** Comment 2 */\n" + " \n" - + " /** Comment 3 */\n" + " public void method2() {}" + "}"); - - testSubject.assignCommentsToDeclarations(node); - List methods = node.findDescendantsOfType(ASTMethodDeclaration.class); - Assert.assertEquals("/** Comment 1 */", AbstractCommentRule.getComment(methods.get(0)).getImage()); - Assert.assertEquals("/** Comment 3 */", AbstractCommentRule.getComment(methods.get(1)).getImage()); - } -} diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentTest.java index ebe03b5c55..958a205874 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentContentTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.documentation; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class CommentContentTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredTest.java index 0eb438e62b..6db9cae9b1 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentRequiredTest.java @@ -8,7 +8,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import org.junit.Test; @@ -17,7 +16,6 @@ import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class CommentRequiredTest extends PmdRuleTst { @Test public void allCommentTypesIgnored() { @@ -26,12 +24,7 @@ public class CommentRequiredTest extends PmdRuleTst { List> propertyDescriptors = getProperties(rule); // remove deprecated properties - for (Iterator> it = propertyDescriptors.iterator(); it.hasNext();) { - PropertyDescriptor property = it.next(); - if (property.description().startsWith("Deprecated!")) { - it.remove(); - } - } + propertyDescriptors.removeIf(property -> property.description().startsWith("Deprecated!")); for (PropertyDescriptor property : propertyDescriptors) { setPropertyValue(rule, property, "Ignored"); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeTest.java index 8c3f5cd307..51a404bcda 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/CommentSizeTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.documentation; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class CommentSizeTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyConstructorTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyConstructorTest.java index cf5c382f6c..0569522532 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyConstructorTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyConstructorTest.java @@ -4,9 +4,12 @@ package net.sourceforge.pmd.lang.java.rule.documentation; +import org.junit.Ignore; + import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") +@Ignore("Ignored until modifiers (@Private, etc) are made accessible " + + "to XPath rules without deprecation warning") public class UncommentedEmptyConstructorTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyMethodBodyTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyMethodBodyTest.java index 0e96e541f5..f0d9ae47db 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyMethodBodyTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/documentation/UncommentedEmptyMethodBodyTest.java @@ -6,7 +6,6 @@ package net.sourceforge.pmd.lang.java.rule.documentation; import net.sourceforge.pmd.testframework.PmdRuleTst; -@org.junit.Ignore("Rule has not been updated yet") public class UncommentedEmptyMethodBodyTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotCallSystemExitTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotTerminateVMTest.java similarity index 81% rename from pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotCallSystemExitTest.java rename to pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotTerminateVMTest.java index 3f5dafd202..dbc90d12de 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotCallSystemExitTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/rule/errorprone/DoNotTerminateVMTest.java @@ -1,4 +1,4 @@ -/** +/* * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ @@ -7,6 +7,6 @@ package net.sourceforge.pmd.lang.java.rule.errorprone; import net.sourceforge.pmd.testframework.PmdRuleTst; @org.junit.Ignore("Rule has not been updated yet") -public class DoNotCallSystemExitTest extends PmdRuleTst { +public class DoNotTerminateVMTest extends PmdRuleTst { // no additional unit tests } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java index f377a7f078..402d4ef25a 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypeTestUtilTest.java @@ -4,6 +4,7 @@ package net.sourceforge.pmd.lang.java.types; +import java.io.ObjectStreamField; import java.io.Serializable; import java.lang.annotation.Annotation; import java.util.concurrent.Callable; @@ -19,6 +20,7 @@ import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTAnonymousClassDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration; import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration; +import net.sourceforge.pmd.lang.java.ast.ASTType; import net.sourceforge.pmd.lang.java.ast.TypeNode; import net.sourceforge.pmd.lang.java.symboltable.BaseNonParserTest; import net.sourceforge.pmd.lang.java.types.testdata.SomeClassWithAnon; @@ -43,6 +45,23 @@ public class TypeTestUtilTest extends BaseNonParserTest { Assert.assertTrue(TypeTestUtil.isA(Serializable.class, klass)); } + @Test + public void testIsAFallbackWithUnresolvedClassReference() { // != declaration + + ASTAnnotation annot = + java.parse("import a.b.Test;" + + "class FooBar { @Test void bar() {} }") + .getFirstDescendantOfType(ASTAnnotation.class); + + Assert.assertTrue(TypeTestUtil.isA("a.b.Test", annot)); + Assert.assertTrue(TypeOps.isUnresolved(annot.getTypeMirror())); + + Assert.assertFalse(TypeTestUtil.isA(org.junit.Test.class, annot)); + Assert.assertFalse(TypeTestUtil.isA("org.junit.Test", annot)); + Assert.assertFalse(TypeTestUtil.isA(Override.class, annot)); + Assert.assertFalse(TypeTestUtil.isA("java.lang.Override", annot)); + } + @Test public void testIsAFallbackEnum() { @@ -55,12 +74,60 @@ public class TypeTestUtilTest extends BaseNonParserTest { Assert.assertNull(klass.getType()); Assert.assertTrue(TypeTestUtil.isA("org.FooBar", klass)); - assertIsA(klass, Iterable.class); - assertIsA(klass, Enum.class); - assertIsA(klass, Serializable.class); - assertIsA(klass, Object.class); + assertIsStrictSubtype(klass, Iterable.class); + assertIsStrictSubtype(klass, Enum.class); + assertIsStrictSubtype(klass, Serializable.class); + assertIsStrictSubtype(klass, Object.class); } + + @Test + public void testIsAnArrayClass() { + + ASTType arrayT = + java.parse("import java.io.ObjectStreamField; " + + "class Foo { private static final ObjectStreamField[] serialPersistentFields; }") + .getFirstDescendantOfType(ASTType.class); + + + assertIsExactlyA(arrayT, ObjectStreamField[].class); + assertIsStrictSubtype(arrayT, Object[].class); + assertIsStrictSubtype(arrayT, Serializable.class); + assertIsNot(arrayT, Serializable[].class); + assertIsStrictSubtype(arrayT, Object.class); + } + + @Test + public void testIsAnAnnotationClass() { + + ASTType arrayT = + java.parse("class Foo { org.junit.Test field; }") + .getFirstDescendantOfType(ASTType.class); + + + assertIsExactlyA(arrayT, Test.class); + assertIsStrictSubtype(arrayT, Annotation.class); + assertIsStrictSubtype(arrayT, Object.class); + } + + @Test + public void testIsAPrimitiveArrayClass() { + + ASTType arrayT = + java.parse("import java.io.ObjectStreamField; " + + "class Foo { private static final int[] serialPersistentFields; }") + .getFirstDescendantOfType(ASTType.class); + + + assertIsExactlyA(arrayT, int[].class); + assertIsNot(arrayT, long[].class); + assertIsNot(arrayT, Object[].class); + + assertIsStrictSubtype(arrayT, Serializable.class); + assertIsStrictSubtype(arrayT, Object.class); + } + + @Test public void testIsAFallbackAnnotation() { @@ -158,10 +225,38 @@ public class TypeTestUtilTest extends BaseNonParserTest { } private void assertIsA(TypeNode node, Class type) { - Assert.assertTrue("TypeTestUtil::isA with class arg: " + type.getCanonicalName(), - TypeTestUtil.isA(type, node)); - Assert.assertTrue("TypeTestUtil::isA with string arg: " + type.getCanonicalName(), - TypeTestUtil.isA(type.getCanonicalName(), node)); + assertIsA(node, type, false, true); } + private void assertIsExactlyA(TypeNode node, Class type) { + assertIsA(node, type, true, true); + assertIsA(node, type, false, true); + } + + private void assertIsNot(TypeNode node, Class type) { + assertIsA(node, type, true, false); + assertIsA(node, type, false, false); + } + + private void assertIsNotExactly(TypeNode node, Class type) { + assertIsA(node, type, true, false); + } + + private void assertIsStrictSubtype(TypeNode node, Class type) { + assertIsNotExactly(node, type); + assertIsA(node, type); + } + + private void assertIsA(TypeNode node, Class type, boolean exactly, boolean expectTrue) { + Assert.assertEquals("TypeTestUtil::isA with class arg: " + type.getCanonicalName(), + expectTrue, + exactly ? TypeTestUtil.isExactlyA(type, node) + : TypeTestUtil.isA(type, node)); + Assert.assertEquals("TypeTestUtil::isA with string arg: " + type.getCanonicalName(), + expectTrue, + exactly ? TypeTestUtil.isExactlyA(type.getCanonicalName(), node) + : TypeTestUtil.isA(type.getCanonicalName(), node)); + } + + } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java index ca5b1bff1c..0e9f7e3129 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java @@ -43,7 +43,7 @@ public class TypesTreeDumpTest extends BaseTreeDumpTest { protected @NonNull String normalize(@NonNull String str) { return super.normalize(str) // capture IDs are unstable from run to run - .replaceAll("capture#\\d+", "capture#..."); + .replaceAll("capture#-?\\d+", "capture#..."); } /** diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclarationTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclarationTest.kt index d307a6941a..e728bfb130 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclarationTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTFieldDeclarationTest.kt @@ -5,6 +5,7 @@ package net.sourceforge.pmd.lang.java.ast +import io.kotest.matchers.shouldBe import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind.* @@ -57,6 +58,7 @@ class ASTFieldDeclarationTest : ParserTestSpec({ "@A int x[] = { 2 };" should parseAs { fieldDecl { + it.preferredReportLocation!!.image shouldBe "x" // the ident it::getModifiers shouldBe modifiers { it::getExplicitModifiers shouldBe emptySet() diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclarationTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclarationTest.kt index 2481d67134..331930a0e7 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclarationTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ASTMethodDeclarationTest.kt @@ -30,6 +30,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({ it should haveVisibility(V_PUBLIC) it shouldNot haveExplicitModifier(PUBLIC) it should haveModifier(PUBLIC) + it.preferredReportLocation!!.image shouldBe "foo" modifiers {} unspecifiedChildren(2) @@ -41,6 +42,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({ it should haveVisibility(V_PUBLIC) it should haveExplicitModifier(PUBLIC) it should haveModifier(PUBLIC) + it.preferredReportLocation!!.image shouldBe "kk" modifiers {} unspecifiedChildren(2) @@ -81,6 +83,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({ it shouldNot haveModifier(PUBLIC) it should haveExplicitModifier(PRIVATE) it should haveModifier(PRIVATE) + it.preferredReportLocation!!.image shouldBe "de" unspecifiedChildren(4) @@ -359,6 +362,7 @@ class ASTMethodDeclarationTest : ParserTestSpec({ it::getModifiers shouldBe modifiers { } it::getResultTypeNode shouldBe classType("Override") it::getFormalParameters shouldBe formalsList(0) + it.preferredReportLocation!!.image shouldBe "bar" it::getExtraDimensions shouldBe child { arrayDim {} diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ConstValuesKotlinTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ConstValuesKotlinTest.kt new file mode 100644 index 0000000000..eb9cb398bb --- /dev/null +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ConstValuesKotlinTest.kt @@ -0,0 +1,39 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.ast + +import io.kotest.matchers.shouldBe +import net.sourceforge.pmd.lang.ast.test.shouldBeA +import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol + +/** + * + */ +class ConstValuesKotlinTest : ProcessorTestSpec({ + + + parserTest("Test reference cycle doesn't crash resolution") { + + val acu = parser.parse(""" + class Foo { + static final int I1 = I2; + static final int I2 = I1; + static final int I3 = 0; + } + """.trimIndent()) + + val (i1, i2, i3) = acu.descendants(ASTVariableDeclaratorId::class.java).toList() + + + i1.initializer!!.constValue shouldBe null + i2.initializer!!.constValue shouldBe null + i3.initializer!!.constValue shouldBe 0 + + i3.symbol.shouldBeA { + it.constValue shouldBe 0 + } + } + +}) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt index 115ed72bea..8355cfb388 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/ParserTestSpec.kt @@ -4,17 +4,17 @@ package net.sourceforge.pmd.lang.java.ast -import io.kotest.core.config.Project -import io.kotest.core.spec.style.DslDrivenSpec +import io.kotest.core.config.configuration +import io.kotest.core.spec.DslDrivenSpec import io.kotest.core.spec.style.scopes.Lifecycle import io.kotest.core.spec.style.scopes.RootScope import io.kotest.core.spec.style.scopes.RootTestRegistration +import io.kotest.core.test.createTestName import io.kotest.core.test.TestCaseConfig import io.kotest.core.test.TestContext -import io.kotest.core.test.TestName import io.kotest.core.test.TestType import io.kotest.matchers.Matcher -import io.kotest.runner.junit.platform.IntelliMarker +import io.kotest.matchers.should as kotlintestShould import net.sourceforge.pmd.lang.ast.Node import net.sourceforge.pmd.lang.ast.ParseException import net.sourceforge.pmd.lang.ast.test.Assertions @@ -24,7 +24,7 @@ import net.sourceforge.pmd.lang.ast.test.shouldMatchN import net.sourceforge.pmd.lang.java.types.JTypeMirror import net.sourceforge.pmd.lang.java.types.TypeDslMixin import net.sourceforge.pmd.lang.java.types.TypeDslOf -import io.kotest.matchers.should as kotlintestShould +import net.sourceforge.pmd.lang.ast.test.IntelliMarker /** * Base class for grammar tests that use the DSL. Tests are layered into @@ -42,11 +42,15 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() override fun lifecycle(): Lifecycle = Lifecycle.from(this) override fun defaultConfig(): TestCaseConfig = actualDefaultConfig() + override fun defaultTestCaseConfig(): TestCaseConfig? = defaultTestConfig override fun registration(): RootTestRegistration = RootTestRegistration.from(this) + private fun actualDefaultConfig() = + defaultTestConfig ?: defaultTestCaseConfig() ?: configuration.defaultTestConfig + fun test(name: String, disabled: Boolean = false, test: suspend TestContext.() -> Unit) = registration().addTest( - name = TestName(name), + name = createTestName(name), xdisabled = disabled, test = test, config = actualDefaultConfig() @@ -72,7 +76,7 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() disabled: Boolean = false, spec: suspend GroupTestCtx.() -> Unit) = registration().addContainerTest( - name = TestName(name), + name = createTestName(name), test = { GroupTestCtx(this).spec() }, xdisabled = disabled ) @@ -128,7 +132,7 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() assertions: suspend ParserTestCtx.() -> Unit) { context.registerTestCase( - name = TestName(name), + name = createTestName(name), test = { ParserTestCtx(javaVersion).apply { setup() }.assertions() }, config = actualDefaultConfig(), type = TestType.Test @@ -143,17 +147,13 @@ abstract class ParserTestSpec(body: ParserTestSpec.() -> Unit) : DslDrivenSpec() } - private fun actualDefaultConfig() = - defaultTestConfig ?: defaultTestCaseConfig() - ?: Project.testCaseConfig() - inner class GroupTestCtx(private val context: TestContext) { suspend fun onVersions(javaVersions: List, spec: suspend VersionedTestCtx.() -> Unit) { javaVersions.forEach { javaVersion -> context.registerTestCase( - name = TestName("Java ${javaVersion.pmdName}"), + name = createTestName("Java ${javaVersion.pmdName}"), test = { VersionedTestCtx(this, javaVersion).apply { setup() }.spec() }, config = actualDefaultConfig(), type = TestType.Container diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TypeDisambiguationTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TypeDisambiguationTest.kt index b1ef571abb..fcab903801 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TypeDisambiguationTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/TypeDisambiguationTest.kt @@ -9,13 +9,10 @@ import io.kotest.matchers.types.shouldBeSameInstanceAs import net.sourceforge.pmd.lang.ast.test.* import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.java.symbols.JClassSymbol -import net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger +import net.sourceforge.pmd.lang.java.symbols.table.internal.JavaSemanticErrors import net.sourceforge.pmd.lang.java.types.JClassType -import net.sourceforge.pmd.lang.java.types.TypeOps import kotlin.test.assertEquals -import kotlin.test.assertNotNull import kotlin.test.assertNull -import kotlin.test.assertTrue class TypeDisambiguationTest : ParserTestSpec({ @@ -89,7 +86,7 @@ class TypeDisambiguationTest : ParserTestSpec({ doTest("Unresolved inner type should produce a warning") { - val (node, args) = logger.warnings[SemanticChecksLogger.CANNOT_RESOLVE_MEMBER]!![0] + val (node, args) = logger.warnings[JavaSemanticErrors.CANNOT_RESOLVE_MEMBER]!![0] args.map { it.toString() } shouldBe listOf("Bar", "com.Foo", "an unresolved type") node.shouldBeA { } } @@ -131,12 +128,12 @@ class TypeDisambiguationTest : ParserTestSpec({ doTest("Ambiguous inner type should produce an error (ref in Foo)") { - val (_, args) = logger.errors[SemanticChecksLogger.AMBIGUOUS_NAME_REFERENCE]?.first { it.first == refInFoo }!! + val (_, args) = logger.errors[JavaSemanticErrors.AMBIGUOUS_NAME_REFERENCE]?.first { it.first == refInFoo }!! args.map { it.toString() } shouldBe listOf("Mem", "p.Scratch.A.Mem", "p.Scratch.B.Mem") } doTest("Ambiguous inner type should produce an error (ref in Scratch)") { - val (_, args) = logger.errors[SemanticChecksLogger.AMBIGUOUS_NAME_REFERENCE]?.first { it.first == refInScratch }!! + val (_, args) = logger.errors[JavaSemanticErrors.AMBIGUOUS_NAME_REFERENCE]?.first { it.first == refInScratch }!! args.map { it.toString() } shouldBe listOf("Mem", "p.Scratch.A.Mem", "p.Scratch.B.Mem") } @@ -180,14 +177,14 @@ class TypeDisambiguationTest : ParserTestSpec({ acu.descendants(ASTFieldDeclaration::class.java).map { it.typeNode as ASTClassOrInterfaceType }.toList() fun assertErrored(t: ASTClassOrInterfaceType, expected: Int, actual: Int) { - val errs = logger.errors[SemanticChecksLogger.MALFORMED_GENERIC_TYPE]?.filter { it.first == t } + val errs = logger.errors[JavaSemanticErrors.MALFORMED_GENERIC_TYPE]?.filter { it.first == t } ?: emptyList() assertEquals(errs.size, 1, "`${t.text}` should have produced a single error") errs.single().second.toList() shouldBe listOf(expected, actual) } fun assertNoError(t: ASTClassOrInterfaceType) { - val err = logger.errors[SemanticChecksLogger.MALFORMED_GENERIC_TYPE]?.firstOrNull { it.first == t } + val err = logger.errors[JavaSemanticErrors.MALFORMED_GENERIC_TYPE]?.firstOrNull { it.first == t } assertNull(err, "`${t.text}` should not have produced an error") } @@ -262,14 +259,14 @@ class TypeDisambiguationTest : ParserTestSpec({ acu.descendants(ASTAnnotation::class.java).map { it.typeNode }.toList() fun assertErrored(t: ASTClassOrInterfaceType) { - val errs = logger.errors[SemanticChecksLogger.EXPECTED_ANNOTATION_TYPE]?.filter { it.first == t } + val errs = logger.errors[JavaSemanticErrors.EXPECTED_ANNOTATION_TYPE]?.filter { it.first == t } ?: emptyList() assertEquals(errs.size, 1, "`${t.text}` should have produced a single error") errs.single().second.toList() shouldBe emptyList() } fun assertNoError(t: ASTClassOrInterfaceType) { - val err = logger.errors[SemanticChecksLogger.MALFORMED_GENERIC_TYPE]?.firstOrNull { it.first == t } + val err = logger.errors[JavaSemanticErrors.MALFORMED_GENERIC_TYPE]?.firstOrNull { it.first == t } assertNull(err, "`${t.text}` should not have produced an error") } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/VarDisambiguationTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/VarDisambiguationTest.kt index 5c54acab31..7081ce162c 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/VarDisambiguationTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/ast/VarDisambiguationTest.kt @@ -11,7 +11,7 @@ import net.sourceforge.pmd.lang.ast.test.shouldMatchN import net.sourceforge.pmd.lang.java.JavaParsingHelper import net.sourceforge.pmd.lang.java.symbols.JClassSymbol import net.sourceforge.pmd.lang.java.symbols.JTypeParameterSymbol -import net.sourceforge.pmd.lang.java.symbols.table.internal.SemanticChecksLogger +import net.sourceforge.pmd.lang.java.symbols.table.internal.JavaSemanticErrors class VarDisambiguationTest : ParserTestSpec({ @@ -140,7 +140,7 @@ class Foo { fun JavaParsingHelper.TestCheckLogger.getWarning(key: String, idx: Int, testCode: (JavaNode, List) -> Unit) { val (node, args) = warnings[key]!![idx] - testCode(node, args.map { it.toString() }) + testCode(node as JavaNode, args.map { it.toString() }) } // Hmm, since shouldMatchN looks into the children of the parent, what it sees here @@ -153,7 +153,7 @@ class Foo { doTest("Unresolved field") { - logger.getWarning(SemanticChecksLogger.CANNOT_RESOLVE_MEMBER, 0) { node, args -> + logger.getWarning(JavaSemanticErrors.CANNOT_RESOLVE_MEMBER, 0) { node, args -> args shouldBe listOf("noField", "com.foo.bar.Foo.Inner", "a field access") node.shouldMatchN { @@ -170,7 +170,7 @@ class Foo { doTest("Unresolved field chain") { - logger.getWarning(SemanticChecksLogger.CANNOT_RESOLVE_MEMBER, 1) { node, args -> + logger.getWarning(JavaSemanticErrors.CANNOT_RESOLVE_MEMBER, 1) { node, args -> args shouldBe listOf("noField", "com.foo.bar.Foo.Inner", "a field access") node.shouldMatchN { @@ -189,7 +189,7 @@ class Foo { doTest("Unresolved type var member") { - logger.getWarning(SemanticChecksLogger.CANNOT_RESOLVE_MEMBER, 2) { node, args -> + logger.getWarning(JavaSemanticErrors.CANNOT_RESOLVE_MEMBER, 2) { node, args -> args shouldBe listOf("fofo", "type variable T", "a field access") node.shouldMatchN { @@ -206,7 +206,7 @@ class Foo { doTest("Unresolved type var member (in type ctx)") { - logger.getWarning(SemanticChecksLogger.CANNOT_RESOLVE_MEMBER, 3) { node, args -> + logger.getWarning(JavaSemanticErrors.CANNOT_RESOLVE_MEMBER, 3) { node, args -> args shouldBe listOf("Fofo", "type variable T", "an unresolved type") node.shouldMatchN { diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/AstSymbolTests.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/AstSymbolTests.kt index a62b50b131..cab484e6f8 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/AstSymbolTests.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/AstSymbolTests.kt @@ -7,15 +7,14 @@ package net.sourceforge.pmd.lang.java.symbols.internal import io.kotest.matchers.collections.shouldBeEmpty import io.kotest.matchers.collections.shouldHaveSize import io.kotest.matchers.collections.haveSize +import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.should import io.kotest.matchers.shouldBe import net.sourceforge.pmd.lang.ast.test.* import net.sourceforge.pmd.lang.ast.test.shouldBe import net.sourceforge.pmd.lang.java.ast.* -import net.sourceforge.pmd.lang.java.symbols.JConstructorSymbol -import net.sourceforge.pmd.lang.java.symbols.JFieldSymbol -import net.sourceforge.pmd.lang.java.symbols.JFormalParamSymbol -import net.sourceforge.pmd.lang.java.symbols.JMethodSymbol +import net.sourceforge.pmd.lang.java.symbols.* +import net.sourceforge.pmd.lang.java.types.Substitution import java.lang.reflect.Modifier /** @@ -52,9 +51,11 @@ class AstSymbolTests : ParserTestSpec({ public class InnerC {} } } + + @interface Annot { } """) - val (fooClass, innerItf, innerEnum, innerClass) = acu.descendants(ASTAnyTypeDeclaration::class.java).toList { it.symbol } + val (fooClass, innerItf, innerEnum, innerClass, annot) = acu.descendants(ASTAnyTypeDeclaration::class.java).toList { it.symbol } val (barM, ohioM) = acu.descendants(ASTMethodDeclaration::class.java).toList { it.symbol } @@ -65,6 +66,7 @@ class AstSymbolTests : ParserTestSpec({ innerItf::getModifiers shouldBe (Modifier.PRIVATE or Modifier.ABSTRACT or Modifier.STATIC) innerClass::getModifiers shouldBe (Modifier.PUBLIC) innerEnum::getModifiers shouldBe (Modifier.FINAL or Modifier.STATIC) + annot::getModifiers shouldBe Modifier.ABSTRACT } doTest("should reflect their simple names properly") { @@ -72,6 +74,7 @@ class AstSymbolTests : ParserTestSpec({ innerItf::getSimpleName shouldBe "Inner" innerEnum::getSimpleName shouldBe "EE" innerClass::getSimpleName shouldBe "InnerC" + annot::getSimpleName shouldBe "Annot" } doTest("should reflect their canonical names properly") { @@ -79,10 +82,12 @@ class AstSymbolTests : ParserTestSpec({ innerItf::getCanonicalName shouldBe "com.foo.Foo.Inner" innerEnum::getCanonicalName shouldBe "com.foo.Foo.EE" innerClass::getCanonicalName shouldBe "com.foo.Foo.EE.InnerC" + annot::getCanonicalName shouldBe "com.foo.Annot" } doTest("should reflect their methods") { fooClass.declaredMethods shouldBe listOf(barM, ohioM) + annot.declaredMethods shouldBe emptyList() } doTest("should fetch their methods properly") { @@ -93,6 +98,7 @@ class AstSymbolTests : ParserTestSpec({ with(acu.typeSystem) { fooClass::getSuperclass shouldBe getClassSymbol(java.util.ArrayList::class.java) innerItf::getSuperclass shouldBe OBJECT.symbol + annot::getSuperclass shouldBe OBJECT.symbol innerClass::getSuperclass shouldBe OBJECT.symbol innerEnum::getSuperclass shouldBe getClassSymbol(java.lang.Enum::class.java) } @@ -103,6 +109,7 @@ class AstSymbolTests : ParserTestSpec({ innerEnum.declaredClasses shouldBe listOf(innerClass) innerItf.declaredClasses shouldBe emptyList() innerClass.declaredClasses shouldBe emptyList() + annot.declaredClasses shouldBe emptyList() } doTest("should reflect their declaring type") { @@ -110,6 +117,7 @@ class AstSymbolTests : ParserTestSpec({ innerEnum::getEnclosingClass shouldBe fooClass innerItf::getEnclosingClass shouldBe fooClass innerClass::getEnclosingClass shouldBe innerEnum + annot::getEnclosingClass shouldBe null } doTest("(enums) should reflect enum constants as fields") { @@ -128,6 +136,12 @@ class AstSymbolTests : ParserTestSpec({ it::getModifiers shouldBe (Modifier.PUBLIC or Modifier.STATIC or Modifier.FINAL) } } + + doTest("(annotations) should have j.l.Annotation as super interface") { + val annotSym = annot.typeSystem.getClassSymbol(java.lang.annotation.Annotation::class.java)!! + annot.superInterfaces shouldBe listOf(annotSym) + annot.getSuperInterfaceTypes(Substitution.EMPTY) shouldBe listOf(annot.typeSystem.declaration(annotSym)) + } } @@ -383,6 +397,14 @@ class AstSymbolTests : ParserTestSpec({ point2Record::getSimpleName shouldBe "Point2" } + doTest("should reflect their superclass properly") { + pointRecord.superclass.shouldBeA { + it::getCanonicalName shouldBe "java.lang.Record" // even if unresolved bc of host jdk + } + pointRecord::getSimpleName shouldBe "Point" + point2Record::getSimpleName shouldBe "Point2" + } + doTest("Should have a canonical ctor") { pointRecord::getConstructors shouldBe listOf(canonCtor1) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/ReflectedFieldSymbolTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/ReflectedFieldSymbolTest.kt index 7b4f6ac432..cd6399a95d 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/ReflectedFieldSymbolTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/ReflectedFieldSymbolTest.kt @@ -7,7 +7,6 @@ package net.sourceforge.pmd.lang.java.symbols.internal import io.kotest.core.spec.style.WordSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import io.kotest.property.arbitrary.filterNot import javasymbols.testdata.impls.IdenticalToSomeFields import javasymbols.testdata.impls.SomeFields @@ -35,7 +34,8 @@ class ReflectedFieldSymbolTest : WordSpec({ } "reflect its modifiers properly" { - TestClassesGen.filterNot { it.isArray }.forAllEqual { + //TestClassesGen.filterNot { it.isArray }.forAllEqual { + TestClassesGen.filter_fixed { !it.isArray }.forAllEqual { Pair( classSym(it)!!.declaredFields.map { it.simpleName to it.modifiers }, it.declaredFields.map { it.name to it.modifiers } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/Utils.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/Utils.kt index 8b1f62f24d..7a4c1e3191 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/Utils.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/symbols/internal/Utils.kt @@ -8,6 +8,7 @@ import io.kotest.assertions.withClue import io.kotest.matchers.collections.haveSize import io.kotest.matchers.should import io.kotest.property.* +import io.kotest.property.arbitrary.filter import net.sourceforge.pmd.lang.java.symbols.JClassSymbol import net.sourceforge.pmd.lang.java.symbols.SymbolResolver import net.sourceforge.pmd.lang.java.types.testTypeSystem @@ -43,6 +44,13 @@ suspend fun Gen.forAllEqual(test: (T) -> Pair) { } /** Generator of test instances. */ +@Deprecated("can be removed once https://github.com/kotest/kotest/issues/1815 is released") +fun Arb.filter_fixed(predicate: (A) -> Boolean) = object : Arb() { + override fun edgecases(): List = this@filter_fixed.edgecases().filter(predicate) + override fun values(rs: RandomSource): Sequence> = this@filter_fixed.values(rs).filter { predicate(it.value) } + override fun sample(rs: RandomSource): Sample = this@filter_fixed.samples(rs).filter { predicate(it.value) }.first() +} + object TestClassesGen : Arb>() { override fun edgecases(): List> = listOf(java.lang.Object::class.java, @@ -51,13 +59,14 @@ object TestClassesGen : Arb>() { Integer.TYPE, Array::class.java) - override fun values(rs: RandomSource): Sequence>> { - val someClasses = getClassesInPackage(javaClass.`package`.name + ".internal.testdata").asSequence() - - return someClasses.map { Sample(it) } + override fun sample(rs: RandomSource): Sample> { + val classes = getClassesInPackage() + if (classes.isEmpty()) { + return Sample(java.lang.Object::class.java) + } + return Sample(classes.random(rs.random)) } - /** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * @@ -66,7 +75,7 @@ object TestClassesGen : Arb>() { * @throws ClassNotFoundException * @throws IOException */ - fun getClassesInPackage(packageName: String): List> { + fun getClassesInPackage(packageName: String = javaClass.`package`.name + ".internal.testdata"): List> { val result = ArrayList>() diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/GlbTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/GlbTest.kt index 4ec25713a2..db7fae2567 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/GlbTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/GlbTest.kt @@ -7,15 +7,21 @@ package net.sourceforge.pmd.lang.java.types import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.collections.shouldContainExactly import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder +import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.shouldBe import io.kotest.property.PropTestConfig import io.kotest.property.checkAll import io.kotest.property.forAll +import io.mockk.InternalPlatformDsl.toArray +import net.sourceforge.pmd.lang.ast.test.shouldBeA import net.sourceforge.pmd.lang.java.types.testdata.LubTestData import net.sourceforge.pmd.lang.java.types.testdata.LubTestData.* import java.io.Serializable /** + * Tests "the greatest lower bound" (glb). + * See net.sourceforge.pmd.lang.java.types.TypeSystem.glb(Collection). + * * @author Clément Fournier */ class GlbTest : FunSpec({ @@ -46,7 +52,7 @@ class GlbTest : FunSpec({ test("Test intersection left associativity") { - checkAll(PropTestConfig(-1697903442944791680), ts.allTypesGen, ts.allTypesGen, ts.allTypesGen) { t, s, r -> + checkAll(ts.allTypesGen, ts.allTypesGen, ts.allTypesGen) { t, s, r -> if (canIntersect(t, s, r)) { glb(glb(t, s), r) shouldBe glb(t, s, r) } @@ -69,6 +75,30 @@ class GlbTest : FunSpec({ glb(t_List, `t_List{?}`) shouldBe `t_List{?}` } + + test("Test GLB corner cases") { + + glb(t_Iterable[`?` extends t_Number], t_Iterable[t_String]).shouldBeA { + it.components.shouldContainExactly(t_Iterable[`?` extends t_Number], t_Iterable[t_String]) + } + glb(`t_ArrayList{Integer}`, ts.NULL_TYPE) shouldBe ts.NULL_TYPE + glb(`t_ArrayList{Integer}`, t_Iterable[`?` extends t_Number], t_Iterable[t_String]).shouldBeA { + it.components.shouldContainExactly(`t_ArrayList{Integer}`, t_Iterable[t_String]) + } + + glb(`t_List{? extends Number}`, `t_Collection{Integer}`).shouldBeA { + it.components.shouldContainExactly(`t_List{? extends Number}`, `t_Collection{Integer}`) + } + + glb(t_List.toArray(), t_Iterable).shouldBeA { + it.components.shouldContainExactly(t_List.toArray(), t_Iterable) + it.inducedClassType.shouldBeNull() + } + glb(`t_List{? extends Number}`, `t_Collection{Integer}`, `t_ArrayList{Integer}`) shouldBe `t_ArrayList{Integer}` + glb(`t_List{? extends Number}`, `t_List{String}`, `t_Enum{JPrimitiveType}`).shouldBeA { + it.components.shouldContainExactly(`t_Enum{JPrimitiveType}`, `t_List{String}`, `t_List{? extends Number}`) + } + } } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/LubTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/LubTest.kt index f2cd6a4816..af1c0a62fe 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/LubTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/LubTest.kt @@ -14,6 +14,9 @@ import net.sourceforge.pmd.lang.java.types.testdata.LubTestData.* import java.io.Serializable /** + * Tests "least upper bound" (lub). + * See net.sourceforge.pmd.lang.java.types.TypeSystem.lub(Collection). + * * @author Clément Fournier */ class LubTest : FunSpec({ diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt index 88d7a72e03..2ccb8e2340 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/SubtypingTest.kt @@ -295,7 +295,7 @@ class SubtypingTest : FunSpec({ test("Captured subtyping wild vs wild") { checkAll(ts.subtypesArb(unchecked = false)) { (t, s) -> - println("$t <: $s") + // println("$t <: $s") capture(t_List[`?` extends t]) shouldSubtypeNoCapture t_List[`?` extends s] } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeGenerationUtil.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeGenerationUtil.kt index b76519172e..b07315cd30 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeGenerationUtil.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeGenerationUtil.kt @@ -10,16 +10,14 @@ import io.kotest.property.Arb import io.kotest.property.Exhaustive import io.kotest.property.RandomSource import io.kotest.property.Sample -import io.kotest.property.arbitrary.arb -import io.kotest.property.arbitrary.filter -import io.kotest.property.arbitrary.map -import io.kotest.property.arbitrary.pair +import io.kotest.property.arbitrary.* import io.kotest.property.exhaustive.exhaustive import net.sourceforge.pmd.lang.java.JavaParsingHelper import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters import net.sourceforge.pmd.lang.java.ast.ParserTestCtx import net.sourceforge.pmd.lang.java.symbols.internal.TestClassesGen +import javax.lang.model.type.TypeMirror import kotlin.streams.toList @@ -28,8 +26,8 @@ val TypeSystem.refTypeGen: Arb get() = RefTypeGenArb(this) val TypeSystem.allTypesGen: Arb get() { val refs = refTypeGen - return arb(edgecases = refs.edgecases() + primitiveGen.values) { rs -> - refTypeGen.values(rs).map { it.value } + return arbitrary(edgecases = refs.edgecases() + primitiveGen.values) { rs -> + refTypeGen.sample(rs).value } } @@ -47,7 +45,7 @@ class RefTypeGenArb(val ts: TypeSystem) : Arb() { ts.SERIALIZABLE, ts.CLONEABLE) - override fun values(rs: RandomSource): Sequence> { + private fun generateTypes(rs : RandomSource) : List { with(TypeDslOf(ts).gen) { val pool: List = listOf( `t_List{String}`, @@ -68,7 +66,7 @@ class RefTypeGenArb(val ts: TypeSystem) : Arb() { it.superTypeSet.toList() + it + it.erasure + it.toArray() } - val testClasses: List = TestClassesGen.map { ts.typeOf(ts.getClassSymbol(it)!!, true) }.values(rs).map { it.value }.toList() + val testClasses: List = TestClassesGen.getClassesInPackage().map { ts.typeOf(ts.getClassSymbol(it), true) } val fullPool = pool.plus(testClasses).shuffled(rs.random) val withParameterized = fullPool.flatMap { if (it is JClassType && it.isRaw) { @@ -77,9 +75,17 @@ class RefTypeGenArb(val ts: TypeSystem) : Arb() { } listOf(it) } - return withParameterized.shuffled(rs.random).asSequence().map { Sample(it) } + return withParameterized } } + + var cachedTypes : List? = null + override fun sample(rs: RandomSource): Sample { + if (cachedTypes == null) { + cachedTypes = generateTypes(rs) + } + return Sample(cachedTypes!!.random(rs.random)) + } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeOpsTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeOpsTest.kt index f4c9a2333a..f46023a7bc 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeOpsTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeOpsTest.kt @@ -8,6 +8,7 @@ import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.collections.shouldContainExactly import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder import io.kotest.property.Arb +import io.kotest.property.arbitrary.arbitrary import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.shuffle import io.kotest.property.checkAll @@ -24,7 +25,11 @@ class TypeOpsTest : FunSpec({ // for any permutation of input, the output should be the same suspend fun checkMostSpecific(input: List, output: List) { - checkAll(Arb.shuffle(input)) { ts -> + fun shuffleOld(list: List) = arbitrary { + list.shuffled(it.random) + } + + checkAll(shuffleOld(input)) { ts -> TypeOps.mostSpecific(ts).shouldContainExactlyInAnyOrder(output) } } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt index d4b85d9443..74e634d12a 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/TypeTestMockingUtil.kt @@ -75,10 +75,10 @@ fun JavaNode.declaredTypeSignatures(): List = typeDeclarations().toL fun JavaNode.declaredMethodSignatures(): List = methodDeclarations().toList { it.genericSignature } fun JavaNode.methodCalls(): DescendantNodeStream = descendants(ASTMethodCall::class.java) -fun JavaNode.firstMethodCall() = descendants(ASTMethodCall::class.java).firstOrThrow() +fun JavaNode.firstMethodCall() = methodCalls().crossFindBoundaries().firstOrThrow() fun JavaNode.ctorCalls(): DescendantNodeStream = descendants(ASTConstructorCall::class.java) -fun JavaNode.firstCtorCall() = descendants(ASTConstructorCall::class.java).firstOrThrow() +fun JavaNode.firstCtorCall() = ctorCalls().crossFindBoundaries().firstOrThrow() fun JavaNode.typeVariables(): MutableList = descendants(ASTTypeParameter::class.java).toList { it.typeMirror } fun JavaNode.varAccesses(name: String): NodeStream = descendants(ASTVariableAccess::class.java).filter { it.name == name } diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt index d5012c4988..3bb43adad1 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/AnonCtorsTest.kt @@ -468,4 +468,31 @@ class AnonCtorsTest : ProcessorTestSpec({ } } + parserTest("Anon in anon") { + // this used to be a stackoverflow + + val (acu, spy) = parser.parseWithTypeInferenceSpy( + """ + public class InputMissingOverrideBadAnnotation { + + Runnable r = new Runnable() { + public void run() { + Throwable t = new Throwable() { + public String toString() { + return "junk"; + } + }; + } + }; + } + """) + + val call = acu.firstCtorCall() + .firstCtorCall() + + spy.shouldBeOk { + call.typeMirror shouldBe java.lang.Throwable::class.decl + } + } + }) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/CtorInferenceTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/CtorInferenceTest.kt index 27ce06e35a..152d5d8c10 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/CtorInferenceTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/CtorInferenceTest.kt @@ -99,7 +99,6 @@ class CtorInferenceTest : ProcessorTestSpec({ parserTest("Generic enum constant ctors") { - logTypeInference(true) val (acu, spy) = parser.parseWithTypeInferenceSpy( """ diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf b/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf deleted file mode 100644 index 43e2c02841..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf +++ /dev/null @@ -1,5 +0,0 @@ -# -# all-java on pmd source tree -# note: add "-debug" to see any parsing/processing exceptions -# --d src/main/java -f text -R rulesets/internal/all-java.xml -language java diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf.example b/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf.example deleted file mode 100644 index 16a9a0cee8..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/coverage/pmd_tests.conf.example +++ /dev/null @@ -1,10 +0,0 @@ -# -# all-java on pmd source tree -# -src text rulesets/internal/all-java.xml -version java 1.5 - -# -# jdk 1.6 source files -# -/usr/java/jdk1.6.0_06/src.zip text rulesets/internal/all-java.xml -version java 1.6 - diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml index 0d2d255eef..16098caa2f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/MissingOverride.xml @@ -156,7 +156,7 @@ public enum EnumWithInterfaces implements MetricKey { - Consider enum methods + Consider enum methods 2 2 9,15 - Avoid false positives when in ambiguous situation - 0 + + Override of generic method with some other overload + 1 + 12 + + The method 'compare(StringBuilder, StringBuilder)' is missing an @Override annotation. + { - Avoid false positives when in ambiguous situation - 0 + + Hierarchy with several bridges + 1 + 30 + + The method 'foo(ASTType)' is missing an @Override annotation. + - EmptyStackException with record top level - 0 + Record override + 1 java 14-preview diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedAssignment.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedAssignment.xml index 0dd7179c5e..62459c0442 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedAssignment.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedAssignment.xml @@ -2809,7 +2809,7 @@ class Foo { - Test ignored name 1 + Test ignored name 1 (method param, reportUnusedVariables) true 0 - Test ignored name 2 + Test ignored name 2 (single underscore, reportUnusedVariables) true 0 - Test ignored name 2 + Test ignored name 3 (reportUnusedVariables) true 1 - Test ignored name 2 + Test ignored name 3 (!reportUnusedVariables) false 0 + + + Call chain with side-effects in try + 1 + + The initializer for variable 'a' is never used (overwritten on line 7) + + + + + + + Explicit this ctor call + 1 + 4 + + The initializer for field 'field' is never used (overwritten on line 10) + + + + + + Field access on something else than this + 0 + 5) { + t.field = 5; + } + } + } + ]]> + + + + Assignment to an ignorable prefix increment + 2 + 4,6 + + The initializer for variable 'd' is never used (overwritten on line 6) + The value assigned to variable 'd' is never used + + + + + + + Static field reassignment + 1 + 2 + + The field initializer for 'b' is never used (overwritten on line 4) + + + + + + Static field reassignment with ctor + 1 + 2 + + The field initializer for 'b' is never used (overwritten on line 7) + + + + + + Branches in switch + 0 + 0xBF) cc = 1; + else cc = 0; + break; + + case 1: + use(cc); break; + + case 2: + cc = use(cc); break; + } + } + return ""; + } + } + ]]> + + + + This field in method + + 0 + interceptors; + private int preProcessIndex = -1; + + public void applyPreProcess(NativeWebRequest request, Callable task) throws Exception { + for (CallableProcessingInterceptor interceptor : this.interceptors) { + interceptor.preProcess(request, task); + this.preProcessIndex++; + } + } + } + ]]> + + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/documentation/xml/CommentRequired.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/documentation/xml/CommentRequired.xml index 6ad1e12f55..4f5cea0d27 100755 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/documentation/xml/CommentRequired.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/documentation/xml/CommentRequired.xml @@ -165,6 +165,7 @@ public class CommentRequired implements Serializable { #1684 whitelist serialPersistentFields 0 Test @override methods unwanted Unwanted 2 + + 9,16 @@ -1385,6 +1387,92 @@ public class Foo { } Closeables.close(stream, false); } +} + ]]> + + + + [java] [6.27.0] Exception applying rule CloseResource on file ... java.lang.NullPointerException #2755 + 0 + + + + + CloseResource with var + 1 + 4 + + + + + #2764 false-negative when re-assigning connection + java.sql.Connection,java.sql.Statement,java.sql.ResultSet + 1 + 7 + + 'c' is reassigned, but the original instance is not closed + + + + + + #2764 false-negative when re-assigning connection - no problem when closed before + java.sql.Connection,java.sql.Statement,java.sql.ResultSet + 0 + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotCallSystemExit.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotTerminateVM.xml similarity index 54% rename from pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotCallSystemExit.xml rename to pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotTerminateVM.xml index 931f5f1830..82fbeba58b 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotCallSystemExit.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/DoNotTerminateVM.xml @@ -6,9 +6,15 @@ basic violations - 1 + 2 basic violations with Runtime - 1 + 2 + + + system exit in main + 0 + + + + + system exit in anonymous class inside main + 1 + + + diff --git a/pmd-lang-test/pom.xml b/pmd-lang-test/pom.xml index 2d56046235..e4212445ce 100644 --- a/pmd-lang-test/pom.xml +++ b/pmd-lang-test/pom.xml @@ -62,32 +62,11 @@ package - - dokka + javadocJar - - org.apache.maven.plugins - maven-jar-plugin - - - kotlin-javadoc - package - - jar - - - ${project.build.directory}/dokka/pmd-lang-test - javadoc - - - - @@ -130,12 +109,6 @@ compile
    - - io.kotest - kotest-runner-console-jvm - compile - - org.jetbrains annotations diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt index 694d0875c0..e83ff59988 100644 --- a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/BaseParsingHelper.kt @@ -54,11 +54,15 @@ abstract class BaseParsingHelper, T : RootNode * defined by the language module). */ fun getVersion(version: String?): LanguageVersion { - val language = LanguageRegistry.getLanguage(langName) ?: throw AssertionError("'$langName' is not a supported language (available ${LanguageRegistry.getLanguages()})") + val language = language return if (version == null) language.defaultVersion else language.getVersion(version) ?: throw AssertionError("Unsupported version $version for language $language") } + private val language: Language + get() = LanguageRegistry.getLanguage(langName) + ?: throw AssertionError("'$langName' is not a supported language (available ${LanguageRegistry.getLanguages()})") + val defaultVersion: LanguageVersion get() = getVersion(params.defaultVerString) @@ -206,7 +210,8 @@ abstract class BaseParsingHelper, T : RootNode * Execute the given [rule] on the [code]. Produce a report with the violations * found by the rule. The language version of the piece of code is determined by the [params]. */ - fun executeRule(rule: Rule, code: String): Report { + @JvmOverloads + fun executeRule(rule: Rule, code: String, filename: String = "testfile.${language.extensions[0]}"): Report { val rules = RulesetsFactoryUtils.defaultFactory().createSingleRuleRuleSet(rule) val configuration = PMDConfiguration() diff --git a/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt new file mode 100644 index 0000000000..d7ad20eea0 --- /dev/null +++ b/pmd-lang-test/src/main/kotlin/net/sourceforge/pmd/lang/ast/test/IntelliMarker.kt @@ -0,0 +1,21 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.ast.test + + +import org.junit.jupiter.api.TestFactory +import org.junit.jupiter.api.condition.EnabledIfSystemProperty + +/** + * This is to trick Intellij into making subclasses executable (because of @TestFactory). + * But Junit does not use it because of the unsatisfiable condition. This comes from + * Kotest, but was removed in 4.2.0 without explanation. + */ +interface IntelliMarker { + @EnabledIfSystemProperty(named = "wibble", matches = "wobble") + @TestFactory + fun primer() { + } +} diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractLanguageVersionTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractLanguageVersionTest.java index f1a4417601..e53b6a81aa 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractLanguageVersionTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractLanguageVersionTest.java @@ -160,8 +160,6 @@ public class AbstractLanguageVersionTest { String rulesetFilenames = props.getProperty("rulesets.filenames"); assertNotNull(rulesetFilenames); - RuleSetFactory factory = RulesetsFactoryUtils.defaultFactory(); - if (rulesetFilenames.trim().isEmpty()) { return; } @@ -171,7 +169,7 @@ public class AbstractLanguageVersionTest { try (InputStream stream = rl.loadClassPathResourceAsStream(r)) { assertNotNull(stream); } - RuleSet ruleset = factory.createRuleSet(r); + RuleSet ruleset = new RuleSetParser().parseFromResource(r); assertNotNull(ruleset); } } diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java index 0394a990a4..2a7fc1a15f 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/AbstractRuleSetFactoryTest.java @@ -290,8 +290,7 @@ public abstract class AbstractRuleSetFactoryTest { } private RuleSet loadRuleSetByFileName(String ruleSetFileName) throws RuleSetNotFoundException { - RuleSetFactory rsf = RulesetsFactoryUtils.defaultFactory(); - return rsf.createRuleSet(ruleSetFileName); + return new RuleSetParser().parseFromResource(ruleSetFileName); } private boolean validateAgainstSchema(String fileName) @@ -389,8 +388,7 @@ public abstract class AbstractRuleSetFactoryTest { // System.out.println("xml2: " + xml2); // Read RuleSet from XML, first time - RuleSetFactory ruleSetFactory = RulesetsFactoryUtils.defaultFactory(); - RuleSet ruleSet2 = ruleSetFactory.createRuleSet(createRuleSetReferenceId(xml2)); + RuleSet ruleSet2 = new RuleSetParser().parseFromResource(createRuleSetReferenceId(xml2)); // Do write/read a 2nd time, just to be sure @@ -403,7 +401,7 @@ public abstract class AbstractRuleSetFactoryTest { // System.out.println("xml3: " + xml3); // Read RuleSet from XML, second time - RuleSet ruleSet3 = ruleSetFactory.createRuleSet(createRuleSetReferenceId(xml3)); + RuleSet ruleSet3 = new RuleSetParser().parseFromResource(createRuleSetReferenceId(xml3)); // The 2 written XMLs should all be valid w.r.t Schema/DTD assertTrue("1st roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")", diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java index db233a7622..12d2b866d5 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java @@ -252,18 +252,10 @@ public abstract class RuleTst { } private Report processUsingStringReader(TestDescriptor test, Rule rule) { - return runTestFromString(test, rule); + return runTestFromString(test.getCode(), rule, test.getLanguageVersion(), test.isUseAuxClasspath()); } - /** - * Run the rule on the given code and put the violations in the report. - */ - public Report runTestFromString(String code, Rule rule, LanguageVersion languageVersion) { - return runTestFromString(code, rule, languageVersion, true); - } - - public Report runTestFromString(String code, Rule rule, LanguageVersion languageVersion, - boolean isUseAuxClasspath) { + public Report runTestFromString(String code, Rule rule, LanguageVersion languageVersion, boolean isUseAuxClasspath) { try { PMDConfiguration config = new PMDConfiguration(); config.setIgnoreIncrementalAnalysis(true); @@ -309,10 +301,6 @@ public abstract class RuleTst { } } - public Report runTestFromString(TestDescriptor test, Rule rule) { - return runTestFromString(test.getCode(), rule, test.getLanguageVersion(), test.isUseAuxClasspath()); - } - /** * getResourceAsStream tries to find the XML file in weird locations if the * ruleName includes the package, so we strip it here. @@ -387,8 +375,8 @@ public abstract class RuleTst { * Run a set of tests of a certain sourceType. */ public void runTests(TestDescriptor[] tests) { - for (int i = 0; i < tests.length; i++) { - runTest(tests[i]); + for (TestDescriptor test : tests) { + runTest(test); } } diff --git a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java index 6fc53ba2a8..726e30d6d9 100644 --- a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java +++ b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java @@ -12,13 +12,11 @@ import static org.mockito.Mockito.when; import java.util.Arrays; -import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleViolation; @@ -27,6 +25,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; import net.sourceforge.pmd.lang.rule.RuleTargetSelector; +import net.sourceforge.pmd.test.lang.DummyLanguageModule.DummyRootNode; import net.sourceforge.pmd.test.lang.ast.DummyNode; public class RuleTstTest { @@ -44,7 +43,7 @@ public class RuleTstTest { when(rule.getTargetSelector()).thenReturn(RuleTargetSelector.forRootOnly()); when(rule.deepCopy()).thenReturn(rule); - Report report = ruleTester.runTestFromString("the code", rule, dummyLanguage, false); + ruleTester.runTestFromString("the code", rule, dummyLanguage, false); verify(rule).start(any(RuleContext.class)); verify(rule).end(any(RuleContext.class)); @@ -66,9 +65,9 @@ public class RuleTstTest { Mockito.doAnswer(new Answer() { private RuleViolation createViolation(int beginLine, String message) { - DummyNode node = new DummyNode(); + DummyNode node = new DummyRootNode(); node.setCoords(beginLine, 1, beginLine + 1, 2); - return new ParametricRuleViolation(rule, "someFile", node, message); + return new ParametricRuleViolation(rule, node, message); } @Override @@ -85,12 +84,6 @@ public class RuleTstTest { testDescriptor.setReinitializeRule(false); testDescriptor.setExpectedLineNumbers(Arrays.asList(5, 15)); - try { - ruleTester.runTest(testDescriptor); - // there should be no assertion failures - // expected line numbers and actual line numbers match - } catch (AssertionError assertionError) { - Assert.fail(assertionError.toString()); - } + ruleTester.runTest(testDescriptor); } } diff --git a/pmd-visualforce/etc/grammar/Vf.jjt b/pmd-visualforce/etc/grammar/Vf.jjt index 2af403e0cb..b15e8a8f03 100644 --- a/pmd-visualforce/etc/grammar/Vf.jjt +++ b/pmd-visualforce/etc/grammar/Vf.jjt @@ -66,6 +66,7 @@ PARSER_END(VfParserImpl) | <#ALPHANUM_CHAR: ( | ) > | <#IDENTIFIER_CHAR: ( | [ "_", "-", ":" ] ) > | <#IDENTIFIER: ()* > +| <#IDENTIFIER_DOTTED: ( )+ > | <#XMLNAME: ( | "_" | ":") ()* > | <#QUOTED_STRING_NO_BREAKS: ( "'" ( ~["'", "\r", "\n"] )* "'" ) | ( "\"" ( ~["\"", "\r", "\n"] )* "\"" ) > @@ -215,7 +216,7 @@ PARSER_END(VfParserImpl) TOKEN : { - > + | > | " > : AfterTagState | " | "!>") > : AfterTagState | " | "/ >") > : AfterTagState diff --git a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/VfParserTest.java b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/VfParserTest.java index f425470314..6ce22de09c 100644 --- a/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/VfParserTest.java +++ b/pmd-visualforce/src/test/java/net/sourceforge/pmd/lang/vf/ast/VfParserTest.java @@ -6,6 +6,8 @@ package net.sourceforge.pmd.lang.vf.ast; import org.junit.Test; +import net.sourceforge.pmd.lang.ast.ParseException; + /** * @author sergey.gorbaty */ @@ -26,4 +28,39 @@ public class VfParserTest extends AbstractVfNodesTest { vf.parse("${\"yes\"}"); } + @Test + public void testAttributeNameWithDot() { + vf.parse(""); + } + + @Test + public void testAttributeNameWithUnderscore() { + vf.parse(""); + } + + @Test + public void testAttributeNameWithColon() { + vf.parse(""); + } + + @Test(expected = ParseException.class) + public void testAttributeNameWithInvalidSymbol() { + vf.parse(""); + } + + @Test(expected = ParseException.class) + public void testAttributeNameWithInvalidDot() { + vf.parse(""); + } + + @Test(expected = ParseException.class) + public void testAttributeNameWithInvalidDotV2() { + vf.parse(""); + } + + @Test(expected = ParseException.class) + public void testAttributeNameWithInvalidDotV3() { + vf.parse(""); + } + } diff --git a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java index c35ac542ad..fbcd1d5dc6 100644 --- a/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java +++ b/pmd-xml/src/main/java/net/sourceforge/pmd/lang/xml/ast/internal/XmlNodeWrapper.java @@ -5,19 +5,22 @@ package net.sourceforge.pmd.lang.xml.ast.internal; -import java.util.ArrayList; +import static java.util.Collections.emptyIterator; + +import java.util.AbstractList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; +import net.sourceforge.pmd.internal.util.IteratorUtil; import net.sourceforge.pmd.lang.rule.xpath.Attribute; import net.sourceforge.pmd.lang.xml.ast.XmlNode; -import net.sourceforge.pmd.util.CompoundIterator; import net.sourceforge.pmd.util.DataMap; import net.sourceforge.pmd.util.DataMap.DataKey; import net.sourceforge.pmd.util.document.FileLocation; @@ -125,47 +128,36 @@ class XmlNodeWrapper implements XmlNode { @Override public Iterator getXPathAttributesIterator() { - List> iterators = new ArrayList<>(); - - // Expose DOM Attributes - final NamedNodeMap attributes = node.getAttributes(); - iterators.add(new Iterator() { - private int index; - - - @Override - public boolean hasNext() { - return attributes != null && index < attributes.getLength(); - } - - - @Override - public Attribute next() { - org.w3c.dom.Node attributeNode = attributes.item(index++); - return new Attribute(XmlNodeWrapper.this, - attributeNode.getNodeName(), - attributeNode.getNodeValue()); - } - - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }); // Expose Text/CDATA nodes to have an 'Image' attribute like AST Nodes if (node instanceof Text) { - iterators.add(Collections.singletonList(new Attribute(this, "Image", ((Text) node).getData())).iterator()); + return Collections.singletonList(new Attribute(this, "Image", ((Text) node).getData())).iterator(); } - // Expose Java Attributes - // iterators.add(new AttributeAxisIterator((net.sourceforge.pmd.lang.ast.Node) p)); + // Expose DOM Attributes + if (node.getAttributes() == null) { + return emptyIterator(); + } else { + return IteratorUtil.map( + asList(node.getAttributes()).iterator(), + n -> new Attribute(this, n.getNodeName(), n.getNodeValue()) + ); + } + } - @SuppressWarnings("unchecked") - Iterator[] it = new Iterator[iterators.size()]; + private static List asList(NamedNodeMap nodeList) { + return new AbstractList() { + @Override + public Node get(int index) { + return nodeList.item(index); + } - return new CompoundIterator<>(iterators.toArray(it)); + + @Override + public int size() { + return nodeList.getLength(); + } + }; } @Override diff --git a/pom.xml b/pom.xml index 5e0a629011..603bdbaea7 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ https://pmd.github.io/ - https://travis-ci.org/pmd/pmd + https://travis-ci.com/pmd/pmd 2002 @@ -76,7 +76,7 @@ - 2020-08-31T16:30:18Z + 2020-10-24T08:17:24Z 8 @@ -85,9 +85,9 @@ ${maven.compiler.test.target} - 1.3.72 - 4.1.2 - 0.10.1 + 1.4.10 + 4.3.0 + 1.4.10.2 5.0 @@ -95,9 +95,9 @@ 8.30 3.1.1 3.13.0 - 1.10.1 + 1.10.8 3.2.0 - 4.7 + 4.7.2 UTF-8 UTF-8 @@ -284,7 +284,7 @@ org.junit.vintage junit-vintage-engine - 5.6.2 + 5.7.0 @@ -415,12 +415,12 @@ net.sourceforge.pmd pmd-core - 6.27.0 + 6.29.0 net.sourceforge.pmd pmd-java - 6.27.0 + 6.29.0 @@ -768,7 +768,7 @@ junit junit - 4.13 + 4.13.1 test
    FileLineRuleNOPMD or AnnotationReason
    " + getSourceCodeFilename() + "1Foo//NOPMDtest